1. 程式人生 > >採用SwipeFreshLayout+Recyclerview實現下拉重新整理和上拉載入更多以及CoordinatorLayout的引入

採用SwipeFreshLayout+Recyclerview實現下拉重新整理和上拉載入更多以及CoordinatorLayout的引入

       之前都是採用PullToRefresh進行下拉重新整理和下拉載入,現在採用谷歌自己的控制元件SwipeFreshLayout,配合Recyclerview來實現這一效果。使用SwipeRefreshLayout可以實現下拉重新整理,前提是佈局裡需要包裹一個可以滑動的子控制元件,可以是ListView或者Recyclerview,這裡我們採用後者,然後在程式碼裡設定OnRefreshListener設定監聽,最後在監聽裡設定重新整理時的資料獲取就可以了。CoordinatorLayout主要是為了實現下滑時標題欄隱藏的功能,以後會單獨介紹。

SwipeRefreshLayout主要方法介紹

SwipeRefreshLayout只能有一個孩子
  • isRefreshing()

    • 判斷當前的狀態是否是重新整理狀態。
  • setColorSchemeResources(int... colorResIds)

    • 設定下拉進度條的顏色主題,引數為可變引數,並且是資源id,可以設定多種不同的顏色,每轉一圈就顯示一種顏色。
  • setOnRefreshListener(SwipeRefreshLayout.OnRefreshListener listener)

    • 設定監聽,需要重寫onRefresh()方法,頂部下拉時會呼叫這個方法,在裡面實現請求資料的邏輯,設定下拉進度條消失等等。
  • setProgressBackgroundColorSchemeResource(int colorRes)

    • 設定下拉進度條的背景顏色,預設白色。
  • setRefreshing(boolean refreshing)

    • 設定重新整理狀態,true表示正在重新整理,false表示取消重新整理。


1.新增build.gradle依賴

compile 'com.android.support:recyclerview-v7:25.0.0'
compile 'com.android.support:cardview-v7:25.3.1'
compile 'com.android.support:design:25.3.1'

2.設定app主題

<application
android:allowBackup=
"true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/Theme.AppCompat.Light.NoActionBar"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application>

3.MainActiviy
public class MainActivity extends AppCompatActivity {

    private SwipeRefreshLayout swipeRefreshLayout;
    private RecyclerView recyclerView;
    private List<String> data = new ArrayList<>();
    public boolean isLoading;
    private RefreshRecyclerAdapter adapter = new RefreshRecyclerAdapter(this, data);
    private Handler handler = new Handler();
    private Toolbar toolbar;
    int topcount = 1;
    int footcount = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.SwipeRefreshLayout);
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
toolbar.setTitle(R.string.notice);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
public void onClick(View v) {
                finish();
}
        });
initData();
initView();
}

    private void initView() {

        //設定載入進度的顏色變化值
swipeRefreshLayout.setColorSchemeResources(R.color.blueStatus,R.color.colorAccent, R.color.colorPrimary, R.color.colorPrimaryDark);
//設定一進入開始重新整理
swipeRefreshLayout.post(new Runnable() {
            @Override
public void run() {
                swipeRefreshLayout.setRefreshing(true);
}
        });
//設定下拉重新整理的監聽器
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
public void onRefresh() {
                handler.postDelayed(new Runnable() {
                    @Override
public void run() {
                        addTopNewData();
}
                }, 2000);
}
        });
        final LinearLayoutManager layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(adapter);
//通過recyclerView的onscrolllistener的監聽來實現上拉載入更多的功能
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            //滾動的三種狀態包括SCROLL_STATE_IDEL 離開狀態 SCROLL_STATE_DRAGGING 手指觸控 SCROLL_STATE_SETLING 加速滑動的時候
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
Log.d("test", "StateChanged = " + newState);
}

            @Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
Log.d("test", "onScrolled");
// 獲取最後一個可見條目
int lastVisibleItemPosition = layoutManager.findLastVisibleItemPosition();
                if (lastVisibleItemPosition + 1 == adapter.getItemCount()) {
                    Log.d("test", "loading executed");
//獲取重新整理狀態
boolean isRefreshing = swipeRefreshLayout.isRefreshing();
                    if (isRefreshing) {
                        adapter.notifyItemRemoved(adapter.getItemCount());
                        return;
}
                    if (!isLoading) {
                        isLoading = true;
handler.postDelayed(new Runnable() {
                            @Override
public void run() {
                                addNewData();
Log.d("test", "load more completed");
isLoading = false;
}
                        }, 1000);
}
                }
            }
        });
//新增點選事件
adapter.setOnItemClickListener(new RefreshRecyclerAdapter.OnItemClickListener() {
            @Override
public void onItemClick(View view, int position) {
                Log.d("test", "item position = " + position);
}

            @Override
public void onItemLongClick(View view, int position) {

            }
        });
}

    /**
     * 下拉載入更多
     */
private void addTopNewData() {

        for (int i = topcount; i < topcount +6; i++) {
            data.add(0,"下拉載入的第"+i+"條資料");
}
        topcount += 6;
adapter.notifyDataSetChanged();
swipeRefreshLayout.setRefreshing(false);
}


    public void initData() {
        handler.postDelayed(new Runnable() {
            @Override
public void run() {
                getData();
}
        }, 1500);
}

    /**
     * 獲取測試資料
     */
private void getData() {
        for (int i =0; i <10; i++) {
            data.add(i,"第"+i+"條資料");
}
        adapter.notifyDataSetChanged();
swipeRefreshLayout.setRefreshing(false);
// adapter.notifyItemRemoved(adapter.getItemCount());
}

    /**
     * 上拉載入更多
     */
public void addNewData() {

        for (int i = footcount; i < footcount+ 6; i++) {
            data.add(data.size(),"上拉載入的第"+i+"條資料");
}
        footcount += 6;
adapter.notifyDataSetChanged();
swipeRefreshLayout.setRefreshing(false);
//adapter.notifyItemRemoved(adapter.getItemCount());
}

}
4.RefreshRecyclerAdapter
public class RefreshRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private static final int TYPE_ITEM = 0;
    private static final int TYPE_FOOTER = 1;//上拉載入更多佈局
private Context context;
    private List data;
    public RefreshRecyclerAdapter(Context context, List data) {
        this.context = context;
        this.data = data;
}

    public interface OnItemClickListener {
        void onItemClick(View view, int position);
        void onItemLongClick(View view, int position);
}

    private OnItemClickListener onItemClickListener;
    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
        this.onItemClickListener = onItemClickListener;
}

    @Override
public int getItemCount() {
        return data.size() == 0 ? 0 : data.size() + 1;
}

    @Override
public int getItemViewType(int position) {
        if (position + 1 == getItemCount()) {
            return TYPE_FOOTER;
} else {
            return TYPE_ITEM;
}
    }

    @Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == TYPE_ITEM) {
            View view = LayoutInflater.from(context).inflate(R.layout.item_base, parent,
                    false);
            return new ItemViewHolder(view);
} else if (viewType == TYPE_FOOTER) {
            View view = LayoutInflater.from(context).inflate(R.layout.view_footer, parent,
                    false);
            return new FootViewHolder(view);
}
        return null;
}

    @Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
        if (holder instanceof ItemViewHolder) {
            ((ItemViewHolder) holder).tv.setText((CharSequence) data.get(position));
            if (onItemClickListener != null) {
                holder.itemView.setOnClickListener(new View.OnClickListener() {
                    @Override
public void onClick(View v) {
                        int position = holder.getLayoutPosition();
onItemClickListener.onItemClick(holder.itemView, position);
}
                });
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
                    @Override
public boolean onLongClick(View v) {
                        int position = holder.getLayoutPosition();
onItemClickListener.onItemLongClick(holder.itemView, position);
                        return false;
}
                });
}
        }
    }


    static class ItemViewHolder extends RecyclerView.ViewHolder {

        TextView tv;
        public ItemViewHolder(View view) {
            super(view);
tv = (TextView) view.findViewById(R.id.tv_date);
}
    }

    static class FootViewHolder extends RecyclerView.ViewHolder {

        public FootViewHolder(View view) {
            super(view);
}
    }
}
5.佈局檔案

ToolBar

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
    <android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true">
        <android.support.v7.widget.Toolbarandroid:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/blueStatus"
android:minHeight="?attr/actionBarSize"
app:layout_scrollFlags="scroll|enterAlways"
app:navigationIcon="?attr/homeAsUpIndicator"
app:theme="@style/Theme.AppCompat.NoActionBar">
        </android.support.v7.widget.Toolbar>
    </android.support.design.widget.AppBarLayout>
</merge>
MainActivity佈局檔案
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
android:orientation="vertical"
>
    <include layout="@layout/toolbar" />
    <android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/SwipeRefreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
        <android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical">
        </android.support.v7.widget.RecyclerView>
    </android.support.v4.widget.SwipeRefreshLayout>
</android.support.design.widget.CoordinatorLayout>
item_base佈局檔案
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="6dp"
android:orientation="vertical"
app:cardBackgroundColor="@color/line"
app:cardPreventCornerOverlap="true"
app:cardUseCompatPadding="true"
app:contentPadding="6dp">
    <LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
        <TextView
android:id="@+id/tv_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="2015-12-11 12:00" />
        <android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:cardBackgroundColor="@color/white"
app:cardPreventCornerOverlap="true"
app:cardUseCompatPadding="true"
app:contentPadding="10dp">
            <TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="2"
android:text="swipefreshlayout測試使用通過。。通過。。通過。" />
        </android.support.v7.widget.CardView>
    </LinearLayout>
</android.support.v7.widget.CardView>
viewFooter佈局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="50dp">
    <RelativeLayout
android:layout_width="match_parent"
android:layout_height="50dp">
        <ProgressBar
android:id="@+id/load_progress"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_centerVertical="true"
android:layout_marginLeft="30dp"/>
        <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="正在努力載入中..."
android:textColor="@android:color/holo_red_dark"
android:textSize="15sp"/>
    </RelativeLayout>
</RelativeLayout>
colors.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#3F51B5</color>
    <color name="colorPrimaryDark">#303F9F</color>
    <color name="colorAccent">#FF4081</color>
    <color name="blueText">#1485C6</color>
    <color name="blueIndexStatus">#67A5EF</color>
    <color name="blueStatus">#1680E2</color>
    <color name="white">#FFFFFFFF</color>
    <color name="dark">#424242</color>
    <color name="red">#FFD4212A</color>
    <color name="grey">#8C8C8C</color>
    <color name="line">#EEEEEE</color>
    <color name="background">#F9F9FA</color>
    <color name="greyBackground">#FFCFCFCF</color>
</resources>