近年来,北京“朝阳群众”因举报多位名人和艺人吸毒而广为人知,传说中“朝阳群众”成为与中情局、克格勃、摩萨德、军情六处齐名的“世界第五大王牌情报组织”。近日,不少网友发现“朝阳群众HD”还上线了App Store。“朝阳群众HD”的App上设有要案、寻人、招领、嫌犯、车辆五个栏目。用户注册登录后,可获得举报途径,文字、拍照、小视频等方式均可完成举报。
本篇来自
三杯两盏
的投稿,为有关NestedScrolling机制的系列文章。本文是这个系列的第一篇,主要是基础的介绍以及相关接口的解释,如果朋友们感兴趣,可以访问作者博客继续阅读。
三杯两盏
的博客地址:
http://blog.csdn.net/al4fun
如今,NestedScrolling机制(可以称为嵌套滚动或嵌套滑动)在各种app中的应用已经十分广泛了,下图是“饿了么”中的一个例子:
当向上滚动列表时,列表的 父view (整个白色部分)会跟着一起向上滑动,当顶部的 banner 收缩到只剩标题栏时,则列表的 父view 保持固定,而列表继续滚动;当向下滚动列表时,则是相反的过程。
这种效果其实也可以通过 CoordinatorLayout 结合 Behavior 来实现,但阅读源码就会发现,CoordinatorLayout 本身是一个 NestedScrollingParent,此外,要实现这种效果还要求可滚动的列表是一个 NestedScrollingChild,也就是说,通过 CoordinatorLayout 结合 Behavior 来实现这种效果,其内部原理也是 NestedScrolling。
NestedScrolling机制 能够让 父view 和 子view 在滚动时进行配合,其基本流程如下:
1.
当 子view 开始滚动之前,可以通知 父view,让其先于自己进行滚动;
2.
子view 自己进行滚动
3.
子view 滚动之后,还可以通知 父view 继续滚动
要实现这样的交互,父View 需要实现 NestedScrollingParent接口,而 子View 需要实现NestedScrollingChild接口。
在这套交互机制中,child 是动作的发起者,parent 只是接受回调并作出响应。
另外:
父view 和 子view 并不需要是直接的父子关系
,即如果 "parent1 包含 parent2,parent2 包含child”,则 parent1 和child 仍能通过 NestedScrolling机制 进行交互。
//主要接口
NestedScrollingChild
NestedScrollingParent
//帮助类
NestedScrollingChildHelper
NestedScrollingParentHelper
上面已经说过,要使用 NestedScrolling机制,父View 需要实现 NestedScrollingParent接口,而 子View 需要实现 NestedScrollingChild接口。
而 NestedScrollingChildHelper 和 NestedScrollingParentHelper 是两个帮助类,当我们在实现 NestedScrollingChild 和 NestedScrollingParent 接口时,使用这两个帮助类可以简化我们的工作。
以上接口和类都在 support-v4包 中提供。另外,一些较新的 系统view 都已经实现了 NestedScrollingChild 或 NestedScrollingParent 接口,也就是说他们直接支持NestedScrolling,例如:
-
NestedScrollView 已实现 NestedScrollingParent 和 NestedScrollingChild
-
RecyclerView 已实现 NestedScrollingChild
-
CoordinatorLayout 已实现 NestedScrollingParent
-
其他的一些
NestedScrollingChild接口
1.
public boolean startNestedScroll(int axes);
开启嵌套滚动流程(实际上是进行了一些嵌套滚动前准备工作)。
当找到了能够配合当前 子view 进行嵌套滚动的 父view 时,返回值为
true
(Returns:true if a cooperative parent was found and nested scrolling has been enabled for the current gesture)。
2. public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow);
在 子view 自己进行滚动之前调用此方法,询问 父view 是否要在 子view 之前进行滚动。
此方法的前两个参数用于告诉 父View 此次要滚动的距离;而 第三 第四 个参数用于 子view 获取 父view 消费掉的距离和 父view 位置的偏移量。