给 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;
        }
    }
}
复制代码
相关文章
相关标签/搜索