滚动吸附Demo地址

Nested滚动分析

存在的目的为了打破传统事件处理机制,允许ViewParent优先响应处理子View的触摸事件

传统事件处理流程

Google 大神 Dave Smith 在很多年前对Android整个touch事件的做了一个很全面的整理,可见 Matering Android’s Touch System,浓缩成简洁的图表示如下:
Nested滚动 - 图1

简单一句话描述就是触摸事件是从Parent -> Child的方向传递,由最上层的Child优先处理事件,如果不处理才会依次向下交由Parent处理

Nested机制后的事件处理流程

Nested滚动 - 图2
如上图所示,Nested滚动机制就是为了打破传统的事件分发机制,让Parent控件能优先接触并且处理消费触摸事件,最典型的应用就是 滚动吸附的效果

Nested机制流程

Nested机制能够让Parent View和Child View在滚动事件消费的过程中进行配合,基本流程如下:

  • 当Child View开始滚动之前,可以通知Parent View,让其先于判断是否需要处理滚动;

  • Parent View不拦截,Child View则消费滚动;

  • Child View滚动之后,还可以通知父view继续滚动。

要实现这样的交互逻辑,首先Parent View要实现NestedScrollingParent接口,而Child View需要实现NestedScrollingChild接口,此机制中Child View是发起方,Parent View是接受回调处理方。
由于此机制是在5.0 Lollipop后提出的,因此在5.0系统上的原生View已经默认支持了Nested机制,并且在Support V7中做了支持。

实现流程

两接口

NestedScrollingChild由Child View实现,NestedScrollingParent由Parent View实现

两帮助类

NestedScrollingParentHelper:主要是对应NestedScrollingParent的接口的实现方法,具体代码可参见
NestedScrollingChildHelper: 主要对应NestedScrollChild接口的实现方法,具体代码可参见
目前大部分的View都对应实现了接口,如:

  • NestedScrollView 已经实现了 NestedScrollingChildNestedScrollingParent 两个接口

  • RecycleView 已经实现了 NestedScrollingChild

  • CoordinatorLayout 实现了 NestedScrollingParent(Behavior机制就是根据此来实现的)

NestedScrollingChild接口解释

具体实现参考NestedScrollingChildHelper,所有回调的核心实现通过此helper工具类实现与Parent回调交互

接口名 解释
startNestedScroll 检查此View的父类是否支持Nested, 如果支持则通过NestedScrollingChildHelper分别回调 onStartNestedScroll 和 onNestedScrollAccepted,代码逻辑参见
dispatchNestedPreScroll ACTION_MOVE分发滚动事件时响应,代码逻辑参见
dispatchNestedScroll ACTION_MOVE开始分发滚动事件,代码逻辑参见
stopNestedScroll ACTION_UP触发时回调,代码逻辑参见

NestedScrollingParent接口解释

忽略不赘述,具体与NestedScrollingChild和NestedScrollingChildHelper的交互逻辑类似

回调交互流程

注:下图忽略了一些Fling等一些非必要的回调
Nested滚动 - 图3

以下从 Child startNestedScroll回调触发到 Parent onStartNestedScroll回调分析下这个流程路径:
Nested滚动 - 图4