1. 程式人生 > >RecyclerView完全解析之下拉重新整理與上拉載入

RecyclerView完全解析之下拉重新整理與上拉載入

(一).前言:

話說RecyclerView已經面市很久,也在很多應用中得到廣泛的使用,在整個開發者圈子裡面也擁有很不錯的口碑,那說明RecyclerView擁有比ListView,GridView之類控制元件有很多的優點,例如:資料繫結,Item View建立,View的回收以及重用等機制。前三三篇文章已經貢呢更新了以下三個部分:

  1. RecyclerView控制元件的基本使用,包括基礎,進階,高階部分,動畫之類(點選進入)
  2. RecyclerView控制元件的實戰例項(點選進入)
  3. RecyclerView控制元件集合AA(Android Annotations)注入框架例項(點選進入)

本來這個專題不打算更新,不過前兩天看到各位童鞋還是挺積極的評論到,希望可以更新RecyclerView加入下拉重新整理和上拉載入更多的功能。正好昨天週末,所以我這邊也就實現了這樣的功能,今天更新一下。具體程式碼已經上傳到下面的專案中,歡迎各位去star和fork一下。

RecyclerView實現的列表,預設情況下面是不帶下拉重新整理和上拉記載更多效果的,但是我在我們的實際專案當中,為了提高使用者體驗,這種效果一般都需要實現,在我以前的部落格中已經重寫了ListView(Android 列表下拉重新整理元件PullToRefreshListView使用)實現上拉重新整理和上拉載入更多效果。現在我們已經學會了ListView,GridView的替代品RecyclerView的基本使用方法,那麼必不可少的也需要實現上拉重新整理和上拉載入更多的效果了。今天我們會通過兩種方式來實現,具體會採用Android的另一控制元件SwipeRefreshLayout。

(二).SwipeRefreshLayout介紹:

SwipeRefrshLayout是Google官方更新的一個Widget,可以實現下拉重新整理的效果。該控制元件整合自ViewGroup在support-v4相容包下,不過我們需要升級support library的版本到19.1以上。基本使用的方法如下:

  • setOnRefreshListener(OnRefreshListener):新增下拉重新整理監聽器
  • setRefreshing(boolean):顯示或者隱藏重新整理進度條
  • isRefreshing():檢查是否處於重新整理狀態
  • setColorSchemeResources():設定進度條的顏色主題,最多設定四種,以前的setColorScheme()方法已經棄用了。

具體使用效果下面我們會看到。

(三).RecyclerView+SwpieRefreshLayout實現下拉重新整理效果:

1.SwipeRefreshLayout本身自帶下拉重新整理的效果,那麼我們可以選擇在RecyclerView佈局外部巢狀一層SwipeRefreshLayout佈局即可,具體佈局檔案如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
< ?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <include layout="@layout/common_top_bar_layout"/>
    <android .support.v4.widget.SwipeRefreshLayout
        android:id="@+id/demo_swiperefreshlayout"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:scrollbars="vertical"
        >
        </android><android .support.v7.widget.RecyclerView
            android:id="@+id/demo_recycler"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            ></android>
    
</linearlayout>

2.接著在Activity中獲取SwipeRefreshLayout控制元件並且設定OnRefreshListener監聽器,同時實現裡邊的onRefresh()方法,在該方法中進行網路請求最新資料,然後重新整理RecyclerView列表同時設定SwipeRefreshLayout的進度Bar的隱藏或者顯示效果。具體程式碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
demo_swiperefreshlayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                Log.d("zttjiangqq""invoke onRefresh...");
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        List<string> newDatas = new ArrayList</string><string>();
                        for (int i = 0; i < 5; i++) {
                            int index = i + 1;
                            newDatas.add("new item" + index);
                        }
                        adapter.addItem(newDatas);
                        demo_swiperefreshlayout.setRefreshing(false);
                        Toast.makeText(RecyclerRefreshActivity.this"更新了五條資料...", Toast.LENGTH_SHORT).show();
                    }
                }5000);
            }
        });

3.除此之外我們也來看一下Adapter和Activity中的其他程式碼,也方便各位童鞋檢視。
RecyclerRefreshActivity.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
public class RecyclerRefreshActivity extends BaseActivity {
    private LinearLayout top_bar_linear_back;
    private TextView top_bar_title;
    private SwipeRefreshLayout demo_swiperefreshlayout;
    private RecyclerView demo_recycler;
    private RefreshRecyclerAdapter adapter;
    private LinearLayoutManager linearLayoutManager;
    private int lastVisibleItem;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.recycler_refresh_layout);
        top_bar_linear_back=(LinearLayout)this.findViewById(R.id.top_bar_linear_back);
        top_bar_linear_back.setOnClickListener(new CustomOnClickListener());
        top_bar_title=(TextView)this.findViewById(R.id.top_bar_title);
        top_bar_title.setText("RecyclerView下拉重新整理,下拉載入更多...");
        demo_swiperefreshlayout=(SwipeRefreshLayout)this.findViewById(R.id.demo_swiperefreshlayout);
        demo_recycler=(RecyclerView)this.findViewById(R.id.demo_recycler);
        //設定重新整理時動畫的顏色,可以設定4個
        demo_swiperefreshlayout.setProgressBackgroundColorSchemeResource(android.R.color.white);
        demo_swiperefreshlayout.setColorSchemeResources(android.R.color.holo_blue_light,
                android.R.color.holo_red_light, android.R.color.holo_orange_light,
                android.R.color.holo_green_light);
        demo_swiperefreshlayout.setProgressViewOffset(false0(int) TypedValue
                .applyDimension(TypedValue.COMPLEX_UNIT_DIP24, getResources()
                        .getDisplayMetrics()));
        linearLayoutManager=new LinearLayoutManager(this);
        linearLayoutManager.setOrientation(OrientationHelper.VERTICAL);
        demo_recycler.setLayoutManager(linearLayoutManager);
        //新增分隔線
        demo_recycler.addItemDecoration(new AdvanceDecoration(this, OrientationHelper.VERTICAL));
        demo_recycler.setAdapter(adapter = new RefreshRecyclerAdapter(this));
        demo_swiperefreshlayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                Log.d("zttjiangqq""invoke onRefresh...");
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        List<String> newDatas = new ArrayList</string><string>();
                        for (int i = 0; i < 5; i++) {
                            int index = i + 1;
                            newDatas.add("new item" + index);
                        }
                        adapter.addItem(newDatas);
                        demo_swiperefreshlayout.setRefreshing(false);
                        Toast.makeText(RecyclerRefreshActivity.this"更新了五條資料...", Toast.LENGTH_SHORT).show();
                    }
                }5000);
            }
        });
          class CustomOnClickListener implements View.OnClickListener{
        @Override
        public void onClick(View v) {
            RecyclerRefreshActivity.this.finish();
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
RefreshRecyclerAdapter.java
[cc lang="java"]
public class RefreshRecyclerAdapter extends RecyclerView.Adapter<RefreshRecyclerAdapter.ViewHolder>{
    private LayoutInflater mInflater;
    private List</string><string> mTitles=null;
    public  RefreshRecyclerAdapter(Context context){
        this.mInflater=LayoutInflater.from(context);
        this.mTitles=new ArrayList</string><string>();
        for (int i=0;i&lt;20;i++){
            int index=i+1;
            mTitles.add("item"+index);
        }
    }
    /**
     * item顯示型別
     * @param parent
     * @param viewType
     * @return
     */

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        final View view=mInflater.inflate(R.layout.item_recycler_layout,parent,false);
        //這邊可以做一些屬性設定,甚至事件監聽繫結
        //view.setBackgroundColor(Color.RED);
        ViewHolder viewHolder=new ViewHolder(view);

        return viewHolder;
    }

    /**
     * 資料的繫結顯示
     * @param holder
     * @param position
     */

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        holder.item_tv.setText(mTitles.get(position));
        holder.itemView.setTag(position);
    }
    @Override
    public int getItemCount() {
        return mTitles.size();
    }

    //自定義的ViewHolder,持有每個Item的的所有介面元素
    public static class ViewHolder extends RecyclerView.ViewHolder {
        public TextView item_tv;
        public ViewHolder(View view){
            super(view);
            item_tv = (TextView) view.findViewById(R.id.item_tv);
        }
    }

    //新增資料
    public void addItem(List</string><string> newDatas) {
        //mTitles.add(position, data);
        //notifyItemInserted(position);
        newDatas.addAll(mTitles);
        mTitles.removeAll(mTitles);
        mTitles.addAll(newDatas);<