为RecyclerView添加下拉刷新(PullToRefresh)功能

在之前的文章中,我们实现了带有header和footer功能的WrapRecyclerView。
实现带header和footer功能的RecyclerView
实现带header和footer功能的RecyclerView——完善篇

现今App中列表的下拉刷新和上拉加载已经是一种习惯了,这两个操作也确实方便很多。
为RecyclerView添加这个功能可以通过多种方法,这里我选用了一种简单的做法。
因为在我们的App中我们一直在使用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{  

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

@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功能进行扩展,目前基本可以满足大部分需求了。所以这部分就到此告一段落了,如果需要其他功能我们以后再来补充。谢谢大家!!
本项目的github地址:https://github.com/chzphoenix/PullToRefreshRecyclerView

你可能感兴趣的:(为RecyclerView添加下拉刷新(PullToRefresh)功能)