NestedScrollingParent, NestedScrollingChild 详解
public class NestedScrollView extends FrameLayout implements NestedScrollingParent, NestedScrollingChild, ScrollingView
可以发现实现了两个没有见过的接口:NestedScrollingParent, NestedScrollingChild,也是这篇文章的主角。 Android 就是通过这两个接口, 来实现 子 View 与父View 之间的嵌套滑动。这样的嵌套滑动机制是在 Android 发布 Lollipop 之后提供的。不过同样在Support v7 中同样支持了。同时 RecycleView 以及 Android 5.0 以上的系统原声 View 大部分都已经支持嵌套滑动了 。
NestedScrolling 机制能够让父 View 和子 View 在滚动式进行配合,而要实现这样的交互机制,首先父 view 要实现 NestedScrollingParent 接口,而子 View 需要实现 NestedScrollingChild 接口,在这套机制中子 View是发起者,父 view 是接受回调并做出响应的。
四个主要接口
// 主要接口
NestedScrollingChild
NestedScrollingParent
// 帮助类
NestedScrollingChildHelper
NestedScrollingParentHelper
正如前面所说的,很多 view 现在都实现了这两个接口:
NestedScrollView 已经实现了 NestedScrollingChild 和 NestedScrollingParent 两个接口
RecycleView 已经实现了 NestedScrollingChild
CoordinatorLayout 实现了 NestedScrollingParent
那实现这两个接口都需要做哪些工作呢?
要实现 NestedScrollingChild 接口,那么需要重写下面几个方法:
// 开始、停止嵌套滚动
public boolean startNestedScroll(int axes);
public void stopNestedScroll();
// 触摸滚动相关
public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow);
public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow);
// 惯性滚动相关 public boolean dispatchNestedPreFling(float velocityX, float velocityY);
public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed);
public boolean dispatchNestedPreFling(float velocityX, float velocityY);
// 设置是否能够滑动
public void setNestedScrollingEnabled(boolean enabled);
public boolean isNestedScrollingEnabled();
要实现 NestedScrollingParent 接口,那么需要重写下面几个方法:
// 当开启、停止嵌套滚动时被调用
public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes);
public void onNestedScrollAccepted(View child, View target, int nestedScrollAxes);
public void onStopNestedScroll(View target);
// 当触摸嵌套滚动时被调用
public void onNestedPreScroll(View target, int dx, int dy, int[] consumed);
public void onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed);
// 当惯性嵌套滚动时被调用
public boolean onNestedPreFling(View target, float velocityX, float velocityY);
public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed);
现在我们大概有些了解了,但是这些方法之间的逻辑关系是怎样的呢?
调用流程
整个对应流程是这样
子view | 父view |
---|---|
startNestedScroll | onStartNestedScroll、onNestedScrollAccepted |
dispatchNestedPreScroll | onNestedPreScroll |
dispatchNestedScroll | onNestedScroll |
stopNestedScroll | onStopNestedScroll |
在子 view 需要滑动的时候例如 ACTION_DOWN 的时候就要调用 startNestedScroll(ViewCompat.SCROLL_AXIS_HORIZONTAL | ViewCompat.SCROLL_AXIS_VERTICAL) 方法来告诉父 view 自己要开始滑动了(实质上是寻找能够配合 child 进行嵌套滚动的 parent)。
父 view 会收到 onStartNestedScroll 回调从而决定是不是要配合子view做出响应。如果需要配合,此方法会返回 true。继而 onStartNestedScroll()回调会被调用。
在滑动事件产生但是子 view 还没处理前可以调用 dispatchNestedPreScroll(0,dy,consumed,offsetInWindow) 这个方法把事件传给父 view 这样父 view 就能在onNestedPreScroll 方法里面收到子 view 的滑动信息,然后做出相应的处理把处理完后的结果通过 consumed 传给子 view。
dispatchNestedPreScroll()之后,child可以进行自己的滚动操作。
如果父 view 需要在子 view 滑动后处理相关事件的话可以在子 view 的事件处理完成之后调用 dispatchNestedScroll 然后父 view 会在 onNestedScroll 收到回调。
最后,滑动结束,调用 onStopNestedScroll() 表示本次处理结束。
过程清楚之后,我们再来看看一些方法的具体的含义,这样更好理解。
public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) ;
此方法的前两个参数用于告诉父 View 此次要滚动的距离;而第三第四个参数用于子 view 获取父 view 消费掉的距离和父 view 位置的偏移量。consumed
参数是一个 int
型的数组,长度为 2,第一个元素是父 view 消费的x
方向的滚动距离;第二个元素是父 view 消费的 y
方向的滚动距离,如果这两个值不为0,则子view需要对滚动的量进行一些修正。正因为有了这个参数,使得我们处理滚动事件的时候,思路更加清晰,不会像以前一样被一堆的滚动参数搞混。
如果parent消费了一部分或全部距离,则此方法返回true。
public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow);
在子 view 自己进行滚动之后调用此方法,询问父view是否还要进行余下 (unconsumed) 的滚动。
前四个参数为输入参数,用于告诉父view已经消费和尚未消费的距离,最后一个参数为输出参数,用于子view获取父view位置的偏移量。
返回值: true if the event was dispatched, false if it could not be dispatched.
public void stopNestedScroll();
最后,stopNestedScroll()方法与startNestedScroll(int axes)对应,用于结束嵌套滚动流程;而惯性滚动相关的两个方法与触摸滚动相关的两个方法类似,这里不再赘述。
这里看三个例子,
1、https://github.com/543441727/MyNestedScrolling
2、这个是我改编的上面一个人写的代码,让它能够像下拉刷新那样工作:
https://github.com/huanshen/NestedScrollingParent-Child
3、https://github.com/qstumn/RefreshLayout
简单来说:
在 NestedScrollingChild 处理点击事件,然后发起滚动请求;
在 NestedScrollingParent 的 onNestedPreScroll 处理事件,是不是要自己消耗;
对于同时这两个接口的ViewGroup,需要在这两个里面都进行处理。如果子类是listview,则可以通过点击事件的拦截来进行控制,如果是recyclerView ,那么就不是点击事件的控制了。
NestedScrollingParent, NestedScrollingChild 详解
Android -- NestedScrolling滑动机制
NestedScrollingParent, NestedScrollingChild 详解的更多相关文章
- Linq之旅:Linq入门详解(Linq to Objects)
示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集 ...
- 架构设计:远程调用服务架构设计及zookeeper技术详解(下篇)
一.下篇开头的废话 终于开写下篇了,这也是我写远程调用框架的第三篇文章,前两篇都被博客园作为[编辑推荐]的文章,很兴奋哦,嘿嘿~~~~,本人是个很臭美的人,一定得要截图为证: 今天是2014年的第一天 ...
- EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解
前言 我比较喜欢安静,大概和我喜欢研究和琢磨技术原因相关吧,刚好到了元旦节,这几天可以好好学习下EF Core,同时在项目当中用到EF Core,借此机会给予比较深入的理解,这里我们只讲解和EF 6. ...
- Java 字符串格式化详解
Java 字符串格式化详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 文中如有纰漏,欢迎大家留言指出. 在 Java 的 String 类中,可以使用 format() 方法 ...
- Android Notification 详解(一)——基本操作
Android Notification 详解(一)--基本操作 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Notification 文中如有纰 ...
- Android Notification 详解——基本操作
Android Notification 详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 前几天项目中有用到 Android 通知相关的内容,索性把 Android Notificatio ...
- Git初探--笔记整理和Git命令详解
几个重要的概念 首先先明确几个概念: WorkPlace : 工作区 Index: 暂存区 Repository: 本地仓库/版本库 Remote: 远程仓库 当在Remote(如Github)上面c ...
- Drawable实战解析:Android XML shape 标签使用详解(apk瘦身,减少内存好帮手)
Android XML shape 标签使用详解 一个android开发者肯定懂得使用 xml 定义一个 Drawable,比如定义一个 rect 或者 circle 作为一个 View 的背景. ...
- Node.js npm 详解
一.npm简介 安装npm请阅读我之前的文章Hello Node中npm安装那一部分,不过只介绍了linux平台,如果是其它平台,有前辈写了更加详细的介绍. npm的全称:Node Package M ...
随机推荐
- 怎么配置Jupyter Notebook默认启动目录?
前言 系统环境:win10 x64:跟环境也没啥关系,在LInux下也一样... 前段时间重换了系统后,发现Jupyter Notebook的默认启动目录不太对呀,所以,就翻到了以前的笔记,还是记在这 ...
- .NET Core快速入门教程 1、开篇:说说.NET Core的那些事儿
一..NET Core的诞生 聊 .NET Core,就不得不说他的爸爸 .NET.当年Java刚刚兴起,如火如荼,微软也非常推崇Java,当时Windows平台的Java虚拟机就是微软按照JVM标准 ...
- 使用PowerApps快速构建基于主题的轻业务应用 —— 进阶篇
作者:陈希章 发表于 2017年12月14日 在上一篇 使用PowerApps快速构建基于主题的轻业务应用 -- 入门篇 中,我用了三个实际的例子演示了如何快速开始使用PowerApps构建轻业务应用 ...
- zkw模板
水平有限,前缀和的前缀和什么的,rbq 两个操作: 1.区间l到r加上一个数x 2.查询区间[l,r]的区间和 #include<iostream> #include<cstdio& ...
- 使用css修改radio、checkbox样式
input[type=radio],input[type=checkbox] { display: inline-block; vertical-align: middle; width: 20px ...
- javascript 正則表達式补充
定义 JavaScript种正則表達式有两种定义方式,定义一个匹配类似 <%XXX%> 的字符串 1. 构造函数 var reg=new RegExp('<%[^%>]+%&g ...
- 使用Logstash来实时同步MySQL数据到ES
上篇讲到了ES和Head插件的环境搭建和配置,也简单模拟了数据作测试 本篇我们来实战从MYSQL里直接同步数据 一.首先下载和你的ES对应的logstash版本,本篇我们使用的都是6.1.1 下载后使 ...
- idea的快捷键
idea的快捷键大全 Alt+回车 导入包,自动修正 Ctrl+N 查找类 Ctrl+Shift+N 查找文件 Ctrl+Alt+L 格式化代码 Ctrl+Alt+O 优化导入的类和包 Alt+ ...
- 转:java泛型
1.为什么需要泛型 转载请注明出处:http://blog.csdn.net/seu_calvin/article/details/52230032 泛型在Java中有很重要的地位,网上很多文章罗列各 ...
- Tomcat在Linux服务器上的BIO、NIO、APR模式设置
一.BIO.NIO.AIO 先了解四个概念: 同步 : 自己亲自出马持银行卡到银行取钱(使用同步IO时,Java自己处理IO读写). 异步 : 委托一小弟拿银行卡到银行取钱,然后给你(使用异步IO时, ...