RecycleView添加下滑到底部的监听

来源:互联网 发布:搜客云优化 编辑:程序博客网 时间:2024/05/12 04:36

我们的日常开发中经常用到下拉刷新,而网上评价最好的开源下拉刷新组件当然还是android-Ultra-Pull-To-Refresh 此组件可以给任何的控件添加下拉刷新功能。当然也包括recycleview了。
可惜android-Ultra-Pull-To-Refresh只是提供了下拉刷新的功能,但是对于列表类的组件,我们日常开发中更多的会用到其上拉加载或者滑到底部自动加载的功能,当然目前来看用户更喜欢滑到底部自动加载的功能。就比如今天说的recycleview我们只能自己给其添加滑到底部加载更多的功能了。

那它的实现原理是神马呢 非常简单:

RecycleView内部有一个滑动监听的抽象类OnScrollListener来接收滚动事件,此类里面有两个实现的方法

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(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(RecyclerView recyclerView, int dx, int dy){}    }

通多源码的注释可以了解到
onScrollStateChanged 当recyclerview的滚动状态发生变化的时候调用。
onScrolled 在布局可见和recycleview滚动的时候调用。

那么思路就是:
(1)在onScrollStateChanged 方法中判断当前的滚动状态是停止滚动的状态。
(2)然后根据api中的方法获得最后可见的位置。
(3)判断当前可见的recycleview中item的条数大于0
(4)判断最后可见的位置大于数大于item总数减一
(5)并且item的总数大于可见的item 这样可以保证超过一个界面的时候才执行。

当满足让面的要求的时候我们就可以通过接口回调执行我们的耗时逻辑 ,并显示出加载的dialog。
因为RecyclerView可以通过layoutManager灵活的转换成列表,表格,和瀑布流。尤其是瀑布流的时候,它的最后可见的位置是不一样的,所以我们必须根据其不同的layoutManager状态获取相对应的最后可见位置。

代码:

 @Override    public void onScrollStateChanged(int state) {        if (state == RecyclerView.SCROLL_STATE_IDLE && mLoadingListener != null) {            LayoutManager layoutManager = getLayoutManager();            int lastVisibleItemPosition;            if (layoutManager instanceof GridLayoutManager) {                lastVisibleItemPosition = ((GridLayoutManager) layoutManager).findLastVisibleItemPosition();            } else if (layoutManager instanceof StaggeredGridLayoutManager) {                int[] into = new int[((StaggeredGridLayoutManager) layoutManager).getSpanCount()];                ((StaggeredGridLayoutManager) layoutManager).findLastVisibleItemPositions(into);                lastVisibleItemPosition = findMax(into);            } else {                lastVisibleItemPosition = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();            }            if (layoutManager.getChildCount() > 0                    && lastVisibleItemPosition >= layoutManager.getItemCount() - 1 &&  layoutManager.getItemCount() > layoutManager.getChildCount()) {                    View footView = mFootViews.get(0);                footView.setVisibility(View.VISIBLE);                mLoadingListener.onLoadMore();            }        }    }

我们可以通过api获取瀑布流的所有的列 ,通过下面的方法找出最下面的一列。将加载的dialog显示在此列的下面。

 private int findMax(int[] lastPositions) {        int max = lastPositions[0];        for (int value : lastPositions) {            if (value > max) {                max = value;            }        }        return max;    }
0 0