Android中的嵌套滑动机制
Android5.0开始提供嵌套滑动机制,用于给子view与父view滑动互动提供更好的交互。
因为在原来的事件分发机制中,如果让子view开始处理事件后,父view有需要在某一个条件下处理事件,只能把子view的事件拦截,在接下来的一个完整的时间系类中,父view就无法继续给子view分发事件了,除非重写dispatchTouchEvent
方法,但是我们知道重写这个方法还是比较有难度的。
在最新的V4包等兼容库中Android都对嵌套滑动提供了支持,主要类如下:
V4
- NestedScrollingParent 嵌套滑动中父view接口
- NestedScrollingParentHelper 嵌套滑动中父view接口的代理实现
- NestedScrollingChild 嵌套滑动中子view接口
- NestedScrollingChildHelper 嵌套滑动中子view接口的代理实现
- NestedScrollView 支持嵌套滑动的ScrollView
design
- CoordinatorLayout 协调器布局
- CoordinatorLayout.Behavior
注意点
- 在嵌套滑动中的一些规则:子view是嵌套滑动的发起者,父view是嵌套滑动的处理者
- 在使用调用嵌套滑动相关的方法时,应该总是使用:ViewCompat,ViewGroupCompat, ViewParentCompat的静态方法来实现兼容
- 应该使用NestedScrollingParentHelper或NestedScrollingChildHelper的对应方法来实现NestedScrollingParent或NestedScrollingChild接口中的方法。
学习嵌套滑动机制
接下来对上述的一些类进行介绍
NestedScrollingChild与NestedScrollingParent
两个接口都有对应的方法,一个需要被嵌套滑动中的父view实现,一个需要被嵌套滑动中的子view实现。
一个嵌套滑动的完成流程应该是这样的。
- 在一个可以滑动的子view中开启嵌套滑动setNestedScrollingEnabled
- 如果要开始一次嵌套滑动,首先应该调用startNestedScroll方法(比如在ACTION_DOWN中),通知父view开始一次嵌套滑动,方法的参数应该是ViewCompatSCROLL_AXIS_HORIZONTAL(横向)或ViewCompatSCROLL_AXIS_VERTICAL(竖向)或者他们的and/or值。这时父view的onStartNestedScroll方法将会被回调,如果父view返回true表示配合此次嵌套滑动,并且父view的onNestedScrollAccepted被调用
- 在子view开始滑动之前,应该先问父view许否需要先滑动,也就是调用dispatchNestedPreScroll方法,这个方法接收三个四个参数:
- dxConsumed 表示子view此次滑动期间将要消耗的水平方法的距离
- dyConsumed 表示子view此次滑动期间将要消耗的垂直方法的距离
- consumed 一个两个长度的数组,这个数组传递给父view,如果父view要先行滑动,将会把消耗的距离通过此数据返回给子view
- offsetInWindow 父view先完成一个滑动后子view在窗口中的偏移值。
- 上面参数可以理解为:dxConsumed和dyConsumed是总的滑动值,传给父view,如果父view需要滑动有消耗掉一些距离,然后把消耗的距离放在consumed中,返回给子view,返回子view根据父view消耗的距离重新计算自己需要滑动的距离,进行滑动。这个过程发送在父view的onNestedPreScroll方法中。
- 子view在根据dispatchNestedPreScroll的返回值,然后计算被父view消耗的距离,根据需要位置
- 子view重新计算自己的滑动距离进行滑动之后,需要调用dispatchNestedScroll方法,此方法接收五个参数
- int dxConsumed 子view在滑动中水平方向消耗的距离
- int dyConsumed 子view在滑动中垂直方向消耗的距离
- int dxUnconsumed 子view在滑动中水平方向没有消耗的距离
- int dyUnconsumed 子view在滑动中垂直方向没有消耗的距离
- int[] offsetInWindow 返回值。父view完成一个滑动后子view在窗口中的偏移值。
- 在完成一系列滑动后,如果需要停止滑动,则子view调用stopNestedScroll然后父view的onStopNestedScroll方法被回调
NestedScrollingParentHelper和NestedScrollingChildHelper分析
NestedScrollingParentHelper和NestedScrollingChildHelper是两个辅助类,分别对象上面分析的两个接口。系统已经给我们封装好了,我们只需要在对应的接口的方法中调用这些辅助类的实现即可。
NestedScrollingChildHelper
NestedScrollingParentHelper
NestedScrollingParentHelper就是记录NestedScrollAxes。
实战
开始实战之前,我也不知道到底那些消耗值改如何写,但是v4包中有个NestedScrollView可以拿来参考。
然后我们可以可以根据嵌套滑动写一个简单的demo,效果如下:
代码实现很简单:
嵌套滑动中的子view:
嵌套滑动中的父view: