Android的NestedScroll机制

Android Touch事件的传递

  1. Activity接收Touch事件回调onTouchEvent,并且将Touch事件分发给DecorView

  2. DecorView接收到Touch事件后,调用dispatchTouchEvent开始分发Touch事件

  3. ViewGroup根据onInterceptTouchEvent判断是否要中断Touch事件传递子View

    • 如果中断的话,则拦截Touch事件,则会回调onTouchEvent
    • 如果不中断的话,则会调用子View的dispatchTouchEvent继续让子View分发Touch事件
  4. 直到有子View消费掉了Touch事件,则整个过程就结束了

问题

这种事件传递的结果就会导致以下问题:
一个View把Touch事件消费之后,其他View就无法接收到该事件,也就无法根据这个事件完成与用户的交互

比如:有一个RecyclerView上有一张图和一个按钮,当ListView滑动的时候,希望这张图先往上平移直至移出屏幕,RecyclerView才能开始滑动,并且在滑动时,按钮可以随着滑动的距离进行Scale的变化

实现NestedScroll

希望支持嵌套滑动操作子View的ViewGroup的子类应该实现该接口。实现该接口的的类应该创建一个final的NestedScrollingParentHelper对象并且将所有的View或者ViewGroup的代理方法都使用它来实现。而View调用嵌套滑动的功能都需要通过ViewGroupCompat或者ViewParentCompat来兼容5.0以下以及以上的系统。

NestedScrollingParentNestedScrollingChildNestedScrollingParentHelperNestedScrollingChildHelper

以上的这些类都是用来帮助更快的实现NesedScroll。

NestScroll机制原理

NestedScroll给View与View之间提供了一种关联的机制,可以使得原来只能单独一个View消费的Touch事件变成多个View之间共同协作处理Touch事件

  • 当子View接收到Touch事件时,会通过实现了NestedScrollingParent接口的ViewParent,告知父View要开始滑动了,而父View此时可以告知实现了NestedScrollingChild接口的其他子View来共享该事件,并且将其他子View所消耗的X,Y返回给接收事件的子View,供其进行计算

步骤

  1. 子View实现NestedScrollingChild接口,并且在内部初始化一个NestedScrollingChildHelper对象,将接口中的函数均用Helper对象进行代理
  2. 父View实现NestedScrollingParent接口,并且在内部初始化一个NestedScrollingParentHelper对象,将接口中的函数均用Helper对象进行代理,同时父View也可以作为NestedScrollingChild存在
  3. 在子View的onInterceptTouchEvent以及onTouchEvent处理Event事件,并且调用dispatchNestedPreScroll以及dispatchNestedScroll方法告知父View处理滑动事件,共同处理手势坐标
Android的NestedScroll机制_第1张图片
NestedScrolling

参考资料

Experimenting with Nested Scrolling
Android Nested Scrolling

你可能感兴趣的:(Android的NestedScroll机制)