为RecyclerView添加下拉刷新功能

简介: 在之前的文章中,我们实现了带有header和footer功能的WrapRecyclerView。现今App中列表的下拉刷新和上拉加载已经是一种习惯了,这两个操作也确实方便很多。为RecyclerView添加这个功能可以通过多种方法,这里我选用了一种简单的做法。基于pulltorefresh这个库。

前言


在之前的文章中,我们实现了带有header和footer功能的WrapRecyclerView

现今App中列表的下拉刷新和上拉加载已经是一种习惯了,这两个操作也确实方便很多。

为RecyclerView添加这个功能可以通过多种方法,这里我选用了一种简单的做法。基于pulltorefresh这个库。


com.loopeer.android.thirdparty:pulltorefresh:<版本>


代码


首先要为WrapRecyclerView添加两个方法,如下:


public int getFirstVisiblePosition(){
        int firstPosition = 0;
        LayoutManager layoutManager = getLayoutManager();
        if(layoutManager instanceof LinearLayoutManager){
            firstPosition = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition();
        }
        if(layoutManager instanceof GridLayoutManager){
            firstPosition = ((GridLayoutManager) layoutManager).findFirstVisibleItemPosition();
        }
        if(layoutManager instanceof StaggeredGridLayoutManager){
            int[] positions = ((StaggeredGridLayoutManager) layoutManager).findFirstVisibleItemPositions(null);
            firstPosition = positions[0];
        }
        return firstPosition;
    }
    public int getLastVisiblePosition(){
        int lastPosition = 0;
        LayoutManager layoutManager = getLayoutManager();
        if(layoutManager instanceof LinearLayoutManager){
            lastPosition = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
        }
        if(layoutManager instanceof GridLayoutManager){
            lastPosition = ((GridLayoutManager) layoutManager).findLastVisibleItemPosition();
        }
        if(layoutManager instanceof StaggeredGridLayoutManager){
            int[] positions = ((StaggeredGridLayoutManager) layoutManager).findLastVisibleItemPositions(null);
            lastPosition = positions[positions.length - 1];
        }
        return lastPosition;
    }
复制代码


这两个方法用于辅助判断滑动时是否到顶或到底,下面会用到。注意对于不同的LayoutManager使用不同的方式来获取。

新建一个PullToRefreshRecyclerView,继承PullToRefreshBase


public class PullToRefreshRecyclerView extends PullToRefreshBase<WrapRecyclerView>{
复制代码


需要重写几个方法来实现功能,如


@Override
    protected boolean isReadyForPullEnd() {
        int lastPosition = getRefreshableView().getLastVisiblePosition();
        RecyclerView.LayoutManager layoutManager = getRefreshableView().getLayoutManager();
        View lastView = layoutManager.findViewByPosition(lastPosition);
        if(lastView != null) {
            int lastBottom = lastView.getBottom();
            return lastPosition == getRefreshableView().getRealItemCount() - 1 && lastBottom <= getRefreshableView().getBottom();
        }
        else{
            return true;
        }
    }
    @Override
    protected boolean isReadyForPullStart() {
        int firstPosition = getRefreshableView().getFirstVisiblePosition();
        RecyclerView.LayoutManager layoutManager = getRefreshableView().getLayoutManager();
        View firstView = layoutManager.findViewByPosition(firstPosition);
        if(firstView != null) {
            int firstTop = firstView.getTop();
            return firstPosition == 0 && firstTop >= 0;
        }
        else{
            return true;
        }
    }
复制代码


这两个方法会在滑动的时候被调用,判断是否已经到列表顶部或底部,如果到顶部或底部就会执行下拉/上拉的操作了。

逻辑比较简单,判断是否显示了第一个/最后一个item,并且它的top/bottom也显示了(说明这个item完整显示出来了)。

还需要重写另外一个方法


@Override
    protected WrapRecyclerView createRefreshableView(Context context, AttributeSet attrs) {
        WrapRecyclerView recyclerView = new WrapRecyclerView(context, attrs);
        recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
            }
            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                if(isReadyForPullStart()){
                    recyclerView.clearFocus();
                }
            }
        });
        recyclerView.setId(R.id.pulltorefresh_recyclerview);
        return recyclerView;
    }
复制代码


这个方法就是创建一个WrapRecyclerView,注意不要忘了setId,否则在Fragment中使用会出现一些问题(回收重建的时候)。


效果


由于基于pulltorefresh库,所有功能库中都实现了,所以重写这几个方法就能实现下拉刷新功能了。实现效果如下

网络异常,图片无法展示
|


如果想改变显示或风格,可以通过pulltorefresh库的api来实现,关于pulltorefresh库的使用大家可以自行查阅相关文档。


目录
相关文章
自己动手写RecyclerView的下拉刷新2
自己动手写RecyclerView的下拉刷新
自己动手写RecyclerView的下拉刷新1
自己动手写RecyclerView的下拉刷新
SwipeRefreshLayout 下拉刷新控件(一)
SwipeRefreshLayout 下拉刷新控件(一)
SwipeRefreshLayout 下拉刷新控件(二)
SwipeRefreshLayout 下拉刷新控件(二)
Flutter 21: 图解 ListView 下拉刷新与上拉加载 (三)【RefreshIndicator】
0 基础学习 Flutter,第二十一步:ListView 上拉加载更多与下拉刷新,解决方案三!
5227 0
|
Android开发
Flutter 18: 图解 ListView 下拉刷新与上拉加载 (二)【NotificationListener】
0 基础学习 Flutter,第十八步:ListView 上拉加载更多与下拉刷新,解决方案二!
5097 0
|
物联网 Android开发 Java
实现 RecyclerView 上拉加载及自动加载
之前在《一步步打造自己的通用上拉加载布局》(如果没有看过,建议先看下这一篇)写到如何实现一个通用的上拉加载布局,本文将基于此进行扩展,实现 RecyclerView 的上拉加载及自动加载。
1338 0