(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

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

  1. RecyclerView的滚动事件分析

    列表的滚动一般分为两种: 手指按下 -> 手指拖拽列表移动 -> 手指停止拖拽 -> 抬起手指 手指按下 -> 手指快速拖拽后抬起手指 -> 列表继续滚动 -> 停 ...

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

    先看一下效果: 本文将讲解如何实现类似于Google+应用中,当列表滚动的时候,ToolBar(以及悬浮操作按钮)的显示与隐藏(向下滚动隐藏,向上滚动显示),这种效果在Material Design ...

  3. Vue 爬坑之路(七)—— 监听滚动事件 实现动态锚点

    前几天做项目的时候,需要实现一个动态锚点的效果 如果是传统项目,这个效果就非常简单.但是放到 Vue 中,就有两大难题: 1. 在没有 jQuery 的 animate() 方法的情况下,如何实现平滑 ...

  4. listView滚动事件

    listView滚动事件 实现接口: android.widget.AbsListView.OnScrollListener Interface definition for a callback t ...

  5. 死磕到底RecyclerView | RecyclerView 的滚动是怎么实现的?

    RecyclerView 是一个展示列表的控件,其中的子控件可以被滚动.这是怎么实现的?以走查源码的方式一探究竟. 切入点:滚动事件 阅读源码时,如何在浩瀚的源码中选择合适的切入点很重要,选好了能少走 ...

  6. js鼠标滑轮滚动事件绑定(兼容主流浏览器)

    /** Event handler for mouse wheel event. *鼠标滚动事件 */ var wheel = function(event) { var delta = 0; if ...

  7. 鼠标滚动事件兼容性 wheel、onwheel

    wheelEvent = "onwheel" in document.createElement("div") ? "wheel" : // ...

  8. JavaScript----分层导航 滚动事件

    分层导航 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3 ...

  9. js网页滚动条滚动事件实例分析

    本文实例讲述了js网页滚动条滚动事件用法.分享给大家供大家参考.具体分析如下: 在做js返回顶部的效果时,要监听网页滚动条滚动事件,这个事件就是:window.onscroll.当onscroll事件 ...

随机推荐

  1. 35个让人惊讶的CSS3动画效果

    1. Pure CSS Coke Can 2. Colorful Clock 3. jQuery DJ Hero 4. Animated Pricing Column 5. Slick jQuery  ...

  2. 电脑技巧 如何保存网页为PDF

    安装Adobe Acrobat X pro(要安装版本,不要绿色版),完成之后再打印机里面可以看到添加了新的Adobe PDF打印机   对于任意的Office文档,都可以直接打印到PDF得到PDF文 ...

  3. 如何设置Apache中的最大连接数

    Apache的主要工作模式有两种:prefork和worker 一.两种模式 prefork模式(缺省模式) prefork是Unix平台上的默认(缺省)MPM,使用多个子进程,每个子进程只有一个线程 ...

  4. PHP传值与传址(引用)

    传值和传引用的区别在于,如果一个参数比较大,占用大量的内存空间,那么传引用的话就会节省拷贝空间. 传值:是把实参的值赋值给行参 ,那么对行参的修改,不会影响实参的值 传引用 :真正的以地址的方式传递参 ...

  5. Initialization failed for Block pool <registering> (Datanode Uuid unassigned) service to IP1:8020 Invalid volume failure config value: 1

    2017-02-27 16:19:44,739 ERROR datanode.DataNode: Initialization failed for Block pool <registerin ...

  6. XWindow、Server、Client和QT、GTK之间的关系

    X WINDOW X Window从逻辑上分为三层:X Server.X Client和X协议.最底层的X Server(X服务器)主要处理输入/输出信息并维护相关资源,它接受来自键盘.鼠标的操作并将 ...

  7. python globals和locals

    文章里面说globals和locals函数返回的是命名空间 - 一个存有对应作用域的所有的变量.方法的字典,注意这里和dir函数返回数组的不一样 Python命名空间的本质 class Test(ob ...

  8. Webwork【05】请求跳转前 xwork.xml 的读取

    个人理解 WebWork 与 Struts2 都是将xml配置文件作为 Controler 跳转的基本依据,WebWork 跳转 Action 前 xml 文件的读取依赖 xwork-1.0.jar, ...

  9. ReactNative踩坑日志——fetch如何向服务器传递参数

    一:简单参数 简单的参数,我们可以使用手动拼接的方式传递. 格式为: fetch(url?key1=val1&key2=val2&...).then((response) => ...

  10. Spring学习笔记六:Spring整合Hibernate

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6785323.html  前言:整合概述 Spring整合Hibernate主要是把Hibernate中常用的S ...