Skip to content

RecyclerView获取滑动距离

本文介绍内容,获取RecyclerView滑动(滚动)的距离。

获取滑动的距离可能并不是一个非常常见的需求。 在一些app中浏览文章内容时,我们可能会注意到一个「Top」按钮。 点击这个按钮可以滑动回文章的顶部。 而刚开始浏览文章时,这个按钮并没有显示出来。向下滑动到一定距离的时候,它才会出现。 如果我们来实现这个功能,最先考虑的应该是获取RecyclerView滑动的距离。 根据滑动的距离,来判断是否应该显示这个「Top」按钮。

前面我们已经用RecyclerView显示一些数据。也知道了如何设置子项点击的监听器。 在实现子项点击的监听器时,我们用到了监听者模式。 而RecyclerView有滑动时监听器RecyclerView.OnScrollListener。 通过这个滑动时监听器,开发者可以获得滑动的状态、距离等等信息。

代码实现

通过addOnScrollListener添加滑动监听。

recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
    @Override
    public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
        super.onScrollStateChanged(recyclerView, newState);
    }

    @Override
    public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
        Log.d(TAG, "onScrolled: dy: " + dy);
    }
});
注意,这里是add,添加监听器。之前我们是set,设置监听器。 都是监听者模式,但具体实现上有区别。

RecyclerView.OnScrollListener是一个抽象类,我们可以选择性地实现它的方法。 onScrolled方法的dy表示的是每一次y方向上的相对滑动距离。向下滑动是正数,向上滑动是负数。

我们可以添加一个变量mmRvScrollY来累计滑动的距离。

recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
    int mmRvScrollY = 0; // 列表滑动距离

    @Override
    public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
        super.onScrollStateChanged(recyclerView, newState);
    }

    @Override
    public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
        mmRvScrollY += dy;
        Log.d(TAG, "onScrolled: mmRvScrollY: " + mmRvScrollY + ", dy: " + dy);
    }
});

每次滑动都累加到mmRvScrollY中。部分打印log如下

onScrolled: mmRvScrollY: 3167, dy: 3
onScrolled: mmRvScrollY: 3169, dy: 2
onScrolled: mmRvScrollY: 3167, dy: -2
onScrolled: mmRvScrollY: 3155, dy: -12

onScrollStateChanged方法给的newState有3个状态

newState的常量名 数值 状态
SCROLL_STATE_IDLE 0 当前没有在滚动,静止状态
SCROLL_STATE_DRAGGING 1 正在被外部输入拖动。比如用户用手指拖动
SCROLL_STATE_SETTLING 2 外部没有拖动它,RecyclerView正在执行滚动动画,滚动到最终的位置

add监听者

我们把目光转到addOnScrollListener方法上来。查阅RecyclerView的源码,可以看到

public void addOnScrollListener(@NonNull OnScrollListener listener) {
    if (mScrollListeners == null) {
        mScrollListeners = new ArrayList<>();
    }
    mScrollListeners.add(listener);
}
RecyclerView持有一个mScrollListeners列表来存放多个OnScrollListener监听器。

对应add方法,还有一个clearOnScrollListeners方法。把存着的OnScrollListener监听器全部清除掉。

之前我们的子项点击监听器只有1个,用set方法。这里的监听器可以有多个,存放在一个列表里。 未来我们使用监听者模式的时候,可以参考OnScrollListener的思路。

工程地址 AndroidTutorial

作者: RustFisher
联系: rf.cs@foxmail.com
博客: rustfisher.com | RustFisher cnblog
示例: AndroidTutorial Gitee, Tutorial Github
链接: https://www.an.rustfisher.com/android/ui/view/recyclerView/scroll_distance/
一家之言,仅当抛砖引玉。如有错漏,还请指出。