RecyclerView的滚动事件OnScrollListener研究

(1)滚动事件分类

列表的滚动一般分为两种:

 1.手指按下 -> 手指拖拽列表移动 -> 手指停止拖拽 -> 抬起手指
 2.手指按下 -> 手指快速拖拽后抬起手指 -> 列表继续滚动 -> 停止滚动

上面的过程的状态变化如下:

1.静止 -> 被迫拖拽移动 -> 静止
2.静止 -> 被迫拖拽移动 -> 自己滚动 -> 静止

(2)监听RecyclerView的滚动

有两种方式可以监听滚动事件:

  1.setOnScrollListener(OnScrollListener listener)
  2.addOnScrollListener(OnScrollListener listener)

其中 setOnScrollListener 由于可能出现空指针的风险,已经过时。建议用addOnScrollListener。

(3)OnScrollListener

/**
 * 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(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){}
}

OnScrollListener类是个抽象类,有两个方法:

void onScrollStateChanged(RecyclerView recyclerView, int newState): 滚动状态变化时回调
void onScrolled(RecyclerView recyclerView, int dx, int dy): 滚动时回调

3.1 onScrollStateChanged(RecyclerView recyclerView, int newState)方法

回调的两个变量的含义:
recyclerView: 当前在滚动的RecyclerView
newState: 当前滚动状态.

其中newState有三种值:

/**
 * The RecyclerView is not currently scrolling.(静止没有滚动)
 */
public static final int SCROLL_STATE_IDLE = 0;

/**
 * The RecyclerView is currently being dragged by outside input such as user touch input.
 *(正在被外部拖拽,一般为用户正在用手指滚动)
 */
public static final int SCROLL_STATE_DRAGGING = 1;

/**
 * The RecyclerView is currently animating to a final position while not under outside control.
 *(自动滚动)
 */
public static final int SCROLL_STATE_SETTLING = 2;

3.2 onScrolled(RecyclerView recyclerView, int dx, int dy)方法

回调的三个变量含义:
recyclerView : 当前滚动的view
dx : 水平滚动距离
dy : 垂直滚动距离

dx > 0 时为手指向左滚动,列表滚动显示右面的内容
dx < 0 时为手指向右滚动,列表滚动显示左面的内容
dy > 0 时为手指向上滚动,列表滚动显示下面的内容
dy < 0 时为手指向下滚动,列表滚动显示上面的内容

(4)canScrollVertically和canScrollHorizontally方法

public boolean canScrollVertically (int direction)
这个方法是判断View在竖直方向是否还能向上,向下滑动。
其中,direction为 -1 表示手指向下滑动(屏幕向上滑动), 1 表示手指向上滑动(屏幕向下滑动)。

public boolean canScrollHorizontally (int direction)
这个方法用来判断 水平方向的滑动

例如:
RecyclerView.canScrollVertically(1)的值表示是否能向下滚动,false表示已经滚动到底部
RecyclerView.canScrollVertically(-1)的值表示是否能向上滚动,false表示已经滚动到顶部

(5)两种判断是否到底部的方法:

5.1方法一:

如果 当前
第一个可见item的位置 + 当前可见的item个数 >= item的总个数
这样就可以判断出来,是在底部了。

loadingMoreListener = 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 (dy > 0) //向下滚动
            {
                int visibleItemCount = mLinearLayoutManager.getChildCount();
                int totalItemCount = mLinearLayoutManager.getItemCount();
                int pastVisiblesItems = mLinearLayoutManager.findFirstVisibleItemPosition();

                if (!loading && (visibleItemCount + pastVisiblesItems) >= totalItemCount) {
                    loading = true;
                    loadMoreDate();
                }
            }
        }
};

通过
visibleItemCount + pastVisiblesItems) >= totalItemCount
来判断是否是底部。

5.2方法二:

通过canScrollVertically 来判断

loadingMoreListener = new RecyclerView.OnScrollListener() {
    @Override
    public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
        super.onScrollStateChanged(recyclerView, newState);
        if(!loading && !recyclerView.canScrollVertically(1)){
            loading = true;
            loadMoreDate();
        }
    }

    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);

//                if (dy > 0) //向下滚动
//                {
//                    int visibleItemCount = mLinearLayoutManager.getChildCount();
//                    int totalItemCount = mLinearLayoutManager.getItemCount();
//                    int pastVisiblesItems = mLinearLayoutManager.findFirstVisibleItemPosition();
//
//                    if (!loading && (visibleItemCount + pastVisiblesItems) >= totalItemCount) {
//                        loading = true;
//                        loadMoreDate();
//                    }
//                }
    }
};

参考:

http://blog.devwiki.net/index.php/2016/06/13/RecyclerView-Scroll-Listener.html

原文地址:https://www.cnblogs.com/xgjblog/p/8135660.html

时间: 2024-10-13 23:48:30

RecyclerView的滚动事件OnScrollListener研究的相关文章

在RecyclerView列表滚动的时候显示或者隐藏Toolbar

先看一下效果: 本文将讲解如何实现类似于Google+应用中,当列表滚动的时候,ToolBar(以及悬浮操作按钮)的显示与隐藏(向下滚动隐藏,向上滚动显示),这种效果在Material Design 清单中有提到: "在合适的地方,当列表向下滚动,app bar可以退出屏幕,以便为内容区域留下更多的空间:而当列表向上滚动回来的时候,app bar又重新显示出来". 注:这里的向下滚动是指滚动到下面查看更多内容,相对应的手势操作其实是往上.同理向上滚动是指查看前面的内容,而手势其实是向下

.Net程序员玩转Android开发---(15)ListView滚动事件

Android中的ListView 可以上下滑动,并且上下活动可以分页加载数据,这一节我们看下ListView的滚动事件. ListView的滚动事件主要通过setOnScrollListener监听器来实现,主要包括两个方法onScroll和onScrollStateChanged方法,onScrollStateChanged主要用来监听滚动状态 在滑动过程中向ListView添加数据 ,ListView滚动的时候主要有三个状态,SCROLL_STATE_TOUCH_SCROLL   ,SCR

vue监听滚动事件 实现动态锚点

前几天做项目的时候,需要实现一个动态锚点的效果 如果是传统项目,这个效果就非常简单.但是放到 Vue 中,就有两大难题: 1. 在没有 jQuery 的 animate() 方法的情况下,如何实现平滑滚动? 2. 如何监听页面滚动事件? 在浏览了大量文章.进行多次尝试之后,终于解决了这些问题 期间主要涉及到了 setTimeout 的递归用法,和 Vue 生命周期中的 mounted 一.锚点实现 在实现平滑滚动之前,得先确保基本的锚点功能 如果没有其他要求,直接用 <a href="#i

强大的CSS:scroll-snap滚动事件停止及元素位置检测

一.Scroll Snap是前端必备技能 CSS Scroll Snap是个非常好用的特性,可以让网页容器滚动停止的时候,无需任何JS代码的参与,浏览器可以自动平滑定位到指定元素的指定位置.类似幻灯片广告效果就可以纯CSS实现. 而且CSS Scroll Snap的兼容性非常好,移动端几乎可以放心使用. 二.源自实际项目的scroll-snap场景 今天下午在实现一个功能需求的时候,正好遇到一个场景非常适合使用Scroll Snap来实现,滑动依次显示人物角色.于是就大胆使用了下,哇,好棒,无需

web前端入门到实战:CSS:scroll-snap滚动事件停止及元素位置检测

一.Scroll Snap是前端必备技能 CSS Scroll Snap是个非常好用的特性,可以让网页容器滚动停止的时候,无需任何JS代码的参与,浏览器可以自动平滑定位到指定元素的指定位置.类似幻灯片广告效果就可以纯CSS实现. 而且CSS Scroll Snap的兼容性非常好,移动端几乎可以放心使用. 二.源自实际项目的scroll-snap场景 今天下午在实现一个功能需求的时候,正好遇到一个场景非常适合使用Scroll Snap来实现,滑动依次显示人物角色.于是就大胆使用了下,哇,好棒,无需

Delphi的基于接口(IInterface)的多播监听器模式(观察者模式 ),利用RTTI实现Delphi的多播事件代理研究

Delphi的基于接口(IInterface)的多播监听器模式(观察者模式 )http://www.cnblogs.com/hezihang/p/6083555.html 利用RTTI实现Delphi的多播事件代理研究http://www.cnblogs.com/hezihang/p/3299481.html

【性能优化】懒、懒加载、懒动画 --- 基于window滚动事件来实时更新DOM的视图状态,以表明是否在规定的可视区,并作有change回调

/* * * 扩展jq原型: 懒.懒加载.懒动画 * --- 基于window滚动事件来实时更新DOM的视图状态,以表明是否在规定的可视区,并作有change回调 * * $jq.viewChange( {top:100,bottom:100,change:function(status){}} ) --- status: 'in'/'out' * $jq.viewChange('off') * * $jq[n].viewChange.status = 'in'/'out' ----- 状态为'

javascript鼠标中键滚动事件介绍

javascript鼠标中键滚动事件介绍:在实际应用中,鼠标的一些事件非常常用,例如,onclick事件.onmouseover事件等,这里就不介绍了,具体可以参阅javascript的onclick事件和javascript的onmouseover事件一章节. 还有一种事件比较少用,那就是鼠标中键滚轮滚动事件,下面就通过代码实例简单介绍一下中键滚轮事件.IE浏览器和谷歌浏览器支持mousewheel事件,也就是鼠标中键滚动事件,但是遗憾的是火狐浏览器并不支持此事件,而是支持DOMMouseSc

页面滚动事件的使用

在现在更加追加页面加载速度和用户体验的情况下,页面的滚动事件使用的越来越多.通常我们使用滚动事件主要做的事情主要有: ajax异步加载,加快页面首次加载的速度 懒加载(或延迟加载):先把HTML元素放到textarea标签中,或把img的链接先放到一个字段里,页面滚动到某个位置时才进行开始加载 顶部导航或侧边导航的焦点跟踪 侧边数字导航的跟踪(例如百度经验) “回到顶部”功能 这两天做了一个demo,大家可以参考一下:页面滚动效果 上图中指出了用滚动事件实现的功能,不过demo中没有实现异步加载