給 RecyclerView 添加基礎的下拉刷新上拉加載

一.添加下拉刷新

依靠SwipeRefreshLayout實現android

1.在xml文件中,使用SwipeRefreshLayout佈局包裹bash

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.SwipeRefreshLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/srl_base"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:scrollbars="vertical">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv_base"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </android.support.v7.widget.RecyclerView>
</android.support.v4.widget.SwipeRefreshLayout>

複製代碼

2.設置刷新的回調ide

mSwpBase.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                //具體的刷新邏輯
                onFresh();
            }
        });
複製代碼

3.刷新結束後,將刷新狀態置爲false佈局

mSwpBase.setRefreshing(false);
複製代碼

4.其餘動畫

//設置進度圈的背景色。
setProgressBackgroundColor(int colorRes);ui

//設置進度動畫的顏色。
setColorSchemeResources(int… colorResIds);spa

//設置進度圈的大小,只有兩個值:DEFAULT、LARGE)
setSize(int size);code

二.添加上拉加載更多(不含footview)

1.使用自帶的addOnScrollListener監聽 添加:cdn

rcBase.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                //滑動狀態改變調用
                onAdd(recyclerView, newState);
            }

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
            }
        });
複製代碼

2.在onAdd方法中判斷是否加載到最後一個xml

public void onAdd(RecyclerView recyclerView, int newState){
        if (newState == RecyclerView.SCROLL_STATE_IDLE && mManager.findLastVisibleItemPosition() == mAdapter.getItemCount()) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    SystemClock.sleep(2000);
                    list.addAll(list);
                    getActivity().runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            mAdapter.notifyDataSetChanged();
                            Toast.makeText(getActivity(), "加載完成", Toast.LENGTH_SHORT).show();
                        }
                    });
                }
            }).start();
        }
    }
複製代碼

其中:

RecyclerView.SCROLL_STATE_IDLE :判斷手指是否離開屏幕

mManager.findLastVisibleItemPosition() :是不是最後一個(爲LinearLayoutManager中方法,GridLayoutManager 繼承 LinearLayoutManager)

三.添加上拉加載更多(含footview)

與不含footiew上拉加載相似,但多了footview,在處理時要加些判斷。

RecyclerView沒有相似listview的addfootview的方法,可是在adapter中有getItemViewType方法,那麼咱們就能夠根據position的不一樣,讓holder在建立的時候建立不一樣的holder

1.在adapter中重寫getItemViewType方法:

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

其中:
position+1:添加了footview數量加1

一樣的在getItemCount中return的list.size()+1

//普通Item View
private static final int TYPE_ITEM = 0;

//底部FootView
private static final int TYPE_FOOTER = 1;

2.在ViewHolder的基礎上,在new一個FootHolder

class FootHolder extends RecyclerView.ViewHolder {
    private final TextView tvFt;
    public FootHolder(View itemView) {
        super(itemView);
        tvFt = (TextView) itemView.findViewById(R.id.tv_ft);
    }
}
複製代碼

注:因爲有兩個ViewHolder在繼承的RecyclerView.Adapter的泛型裏面須要改爲公共父類RecyclerView.ViewHolder

3.在onCreateViewHolder中根據viewType建立不一樣的view,並返回不一樣的holder

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view;
    if (viewType == TYPE_ITEM) {
        view = getActivity().getLayoutInflater().inflate(R.layout.fragment_video, parent, false);
        return new VideoHolder(view);
    } else if (viewType == TYPE_FOOTER) {
        view = getActivity().getLayoutInflater().inflate(R.layout.foot_view, parent, false);
        return new FootHolder(view);
    }
    return null;
}
複製代碼

4.在onBindViewHoder中根據holder的類型加載不用的邏輯

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    if (holder instanceof VideoHolder) {
        VideoBean videoBean = list.get(position);
        VideoHolder videoHolder = (VideoHolder) holder;
        videoHolder.fbVideo.setImageURI(videoBean.getImg());
        videoHolder.tvTitle.setText(videoBean.getTitle());
        //把數據當tag傳到view中,寫一個listener就能夠了
        videoHolder.llVideo.setTag(videoBean);
        videoHolder.llVideo.setOnClickListener(mListerner);
    } else if (holder instanceof FootHolder) {
        FootHolder footHolder = (FootHolder) holder;
        switch (load_more_status) {
            case PULLUP_LOAD_MORE:
                footHolder.tvFt.setText("上拉加載更多");
                break;
            case LOADING_MORE:
                footHolder.tvFt.setText("正在加載更多");
                break;
        }
    }
}
複製代碼

使用instance判斷,而後強轉holder類

//上拉加載更多
public static final int PULLUP_LOAD_MORE = 0;

//正在加載中
public static final int LOADING_MORE = 1;

//上拉加載更多狀態-默認爲0
private int load_more_status = 0;

5.onScrollStateChanged修改

@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
    super.onScrollStateChanged(recyclerView, newState);
    load_more_status = LOADING_MORE;
    if (newState == RecyclerView.SCROLL_STATE_IDLE && getCount() + 1 == mAdapter.getItemCount()) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                load_more_status = PULLUP_LOAD_MORE;
                SystemClock.sleep(2000);
                list.addAll(list);
                getActivity().runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        mAdapter.notifyDataSetChanged();
                        Toast.makeText(getActivity(), "加載完成", Toast.LENGTH_SHORT).show();
                    }
                });
            }
        }).start();
    }
}
複製代碼

四.其餘問題處理

1.當GridLayoutManager添加footview時會形成佈局錯亂:

image

緣由:

GridLayoutManager manager = new GridLayoutManager(getActivity(), 3);

在咱們new GridLayoutManager的時候,傳進去的3

至關於把一行分紅了3份,一個items默認佔1份,也就是一行3個,你的footview也佔1份,因此不會居中。

知道了緣由,改也就好改了

介紹咱們關鍵的類:public static abstract class SpanSizeLookup (GridLayoutManager包下)

繼承後會重寫 getSpanSize方法 默認返回1,也就是一個佈局佔1份

class GridSpanSizeLookop extends GridLayoutManager.SpanSizeLookup {
        @Override
        public int getSpanSize(int position) {
            return 1;
        }
    }
複製代碼

那麼,在這個方法裏面咱們就能夠判斷,當是footview的時候,返回一行就能夠解決問題了。

修改getSpanSize方法的返回值

class GridSpanSizeLookop extends GridLayoutManager.SpanSizeLookup {
    @Override
    public int getSpanSize(int position) {
//        Log.d(TAG, position + "xx" + list.size() + 1);
        if (position == list.size()) {
            return mManager.getSpanCount();
        }
        return 1;
    }
}
複製代碼

最後在adapter中重寫onAttachedToRecyclerView方法:

@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
    super.onAttachedToRecyclerView(recyclerView);
    if (mGridSpanSizeLookup == null) {
        mGridSpanSizeLookup = new GridSpanSizeLookop();
    }
    mManager.setSpanSizeLookup(mGridSpanSizeLookup);
}
複製代碼

另外,也能夠在new GridLayoutManager之後這麼寫:

mManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
    @Override
    public int getSpanSize(int position) {
        return position == list.size() ? mManager.getSpanCount() : 1;
    }
});
複製代碼

2.getSpanSize方法的其餘用法:

經過更改返回值實現下面的佈局

image

代碼:

mManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
    @Override
    public int getSpanSize(int position) {
        return position == list.size() ? mManager.getSpanCount() : 3 - position % 3;
    }
});
複製代碼

3.流式佈局處理 因爲StaggeredGridLayoutManager中沒有setSpanSizeLookup方法,沒法經過上述辦法實現上拉加載,可是StaggeredGridLayoutManager.LayoutParams中有setFullSpan方法能夠達到一樣的效果。

這時候重寫的再也不是onAttachedToRecyclerView方法而是onViewAttachedToWindow方法

//將上拉加載的佈局添加到正中間
@Override
public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) {
    super.onViewAttachedToWindow(holder);
    ViewGroup.LayoutParams layoutParams = holder.itemView.getLayoutParams();
    if (layoutParams != null && layoutParams instanceof StaggeredGridLayoutManager.LayoutParams) {
        //是不是最後一個
        if (holder.getLayoutPosition() == list.size()) {
            StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams) holder.itemView.getLayoutParams();
            p.setFullSpan(true);
            //能夠上拉加載
            mIsFresh = true;
        }
    }
}
複製代碼
相關文章
相關標籤/搜索