针对RecyclerView有很多开源的框架可以直接拿来用,比较有代表性的是BaseRecyclerViewAdapterHelper,功能很强大,具备上拉监听的功能。使用开源的东西固然省时省力,但是前期自定义的Adapter使用较多,不想再更改了,且总使用开源的东西慢慢人都变傻了,这个功能不算复杂,就自己查找相关资料参照实现了。
这个抽象类是我们要实现下拉刷新,上拉加载的关键,其中有onScrollStateChanged 、onScrolled两个方法
/**
* An OnScrollListener can be added to a RecyclerView to receive messages when a scrolling event
* has occurred on that RecyclerView.
* <p>
* @see RecyclerView#addOnScrollListener(OnScrollListener)
* @see RecyclerView#clearOnChildAttachStateChangeListeners()
*
*/
public abstract static class OnScrollListener {
/**
* Callback method to be invoked when RecyclerView's scroll state changes.
*
* @param recyclerView The RecyclerView whose scroll state has changed.
* @param newState The updated scroll state. One of {@link #SCROLL_STATE_IDLE},
* {@link #SCROLL_STATE_DRAGGING} or {@link #SCROLL_STATE_SETTLING}.
*/
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState){}
/**
* Callback method to be invoked when the RecyclerView has been scrolled. This will be
* called after the scroll has completed.
* <p>
* This callback will also be called if visible item range changes after a layout
* calculation. In that case, dx and dy will be 0.
*
* @param recyclerView The RecyclerView which scrolled.
* @param dx The amount of horizontal scroll.
* @param dy The amount of vertical scroll.
*/
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy){}
}
结合以上对两个方法及参数的说明,可知,结合这两个方法可判断出当前是下滑还是上滑动作,覆写方法,结合加入可视区域第一条和最后一条item的位置,可以判断出下拉、上拉的动作,因此完全可以自定义RecyclerView.OnScrollListener实现,关键思路:
完整的自定义RecyclerView.OnScrollListener代码如下:
public class RecyclerViewOnScrollListener extends RecyclerView.OnScrollListener {
//监听回调
private UpPullOnScrollListener listener;
public RecyclerViewOnScrollListener(UpPullOnScrollListener listener) {
this.listener = listener;
}
boolean isUpScroll = false; //是否正在上滑标记
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
LinearLayoutManager manager = (LinearLayoutManager) recyclerView.getLayoutManager();
if (newState == RecyclerView.SCROLL_STATE_IDLE) { //当前未滑动
int itemCount = manager.getItemCount(); //总数
int lastItemPosition = manager.findLastCompletelyVisibleItemPosition();//最后显示的位置
if (lastItemPosition == (itemCount - 1) && isUpScroll) {
listener.onLoadMore();
}
int fristItemPosition = manager.findFirstCompletelyVisibleItemPosition();//第一个显示的位置
if (fristItemPosition == (0) && !isUpScroll){
listener.onRefresh();
}
}
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
// 大于0表示正在向上滑动,小于等于0表示停止或向下滑动
isUpScroll = dy > 0;
}
public interface UpPullOnScrollListener {
public void onLoadMore() ; //上拉加载更多的方法
public void onRefresh() ; //下拉刷新的方法
}
}
1)RecyclerView的 public void addOnScrollListener(@NonNull OnScrollListener listener) 方法实现列表滑动事件的监听,传入的对象为OnScrollListener;
2)用自定义的RecyclerView.OnScrollListener写一个自己业务处理的监听器,eg:
private RecyclerViewOnScrollListener.UpPullOnScrollListener onScrollListener = new RecyclerViewOnScrollListener.UpPullOnScrollListener() {
@Override
public void onLoadMore() { //上拉处理逻辑
}
@Override
public void onRefresh() { //下拉刷新不在此处处理,使用的swipeRefreshLayout实现
}
};
3)调用监听即可:recyclerView.addOnScrollListener(new RecyclerViewOnScrollListener(onScrollListener));
用这个layout实现的下拉刷新效果更好看一些,而且也很方便,此处只写注意要点:
1)布局时 SwipeRefreshLayout 包裹 RecyclerView;
2)所在类实现SwipeRefreshLayout.OnRefreshListener接口;
3)SwipeRefreshLayout实例化对象设置刷新监听setOnRefreshListener(this);
4)覆写public void onRefresh()方法,其中写自己的刷新业务逻辑。