2019独角兽企业重金招聘Python工程师标准>>>
NestedScrolling机制(可以称为嵌套滚动或嵌套滑动)能够让父view和子view在滚动时进行配合,其基本流程如下:
- 当子view开始滚动之前,可以通知父view,让其先于自己进行滚动;
- 子view自己进行滚动
- 子view滚动之后,还可以通知父view继续滚动
要实现这样的交互,父View需要实现NestedScrollingParent接口,而子View需要实现NestedScrollingChild接口。
在这套交互机制中,child是动作的发起者,parent只是接受回调并作出响应。
另外: 父view和子view并不需要是直接的父子关系,即如果“parent1包含parent2,parent2包含child”,则parent1和child仍能通过nestedScrolling机制进行交互。
- NestedScrollView 已实现 NestedScrollingParent和NestedScrollingChild
- RecyclerView 已实现 NestedScrollingChild
- CoordinatorLayout 已实现 NestedScrollingParent
关于动作的方法大概可以分成两类
第一类:主要实现通用的的关联动作,各种view的改变都可以使用。
public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency)
public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency)
第二类:主要实现滚动的动作
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes)
public void onNestedScrollAccepted(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes)
public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target)
public void onNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed)
public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dx, int dy, int[] consumed)
public boolean onNestedFling(CoordinatorLayout coordinatorLayout, View child, View target, float velocityX, float velocityY, boolean consumed)
public boolean onNestedPreFling(CoordinatorLayout coordinatorLayout, View child, View target, float velocityX, float velocityY)
方法之间的具体对应关系如下:
子(发起者) | 父(被回调) |
---|---|
startNestedScroll | onStartNestedScroll、onNestedScrollAccepted |
dispatchNestedPreScroll | onNestedPreScroll |
dispatchNestedScroll | onNestedScroll |
stopNestedScroll | onStopNestedScroll |
流程
可以大致将嵌套滚动的流程概括如下(以触摸滚动为例,惯性滚动(fling)的流程与此类似):
- 调用child的startNestedScroll()来发起嵌套滚动流程(实质是寻找能够配合child进行嵌套滚动的parent)。parent的onStartNestedScroll()会被回调,如果此方法返回true,则onNestedScrollAccepted()也会被回调。
- child每次滚动前,可以先询问parent是否要滚动,即调用dispatchNestedPreScroll(),这会回调到parent的onNestedPreScroll(),parent可以在这个回调中先于child滚动。
- disdispatchNestedPreScroll()之后,child可以进行自己的滚动操作。
- child滚动以后,可以调用dispatchNestedScroll(),会回调到parent的onNestedScroll(),在这里parent可以进行后于child的滚动。 滚动结束,调用stopNestedScroll()。
其他
1、要关联滚动的View需要实现NestedScrollingChild接口,并在用NestedScrollingChildHelper辅助类处理相应的回调 2、需要关联滚动的View的父View需要实现NestedScrollingParent接口,可用NestedScrollingParentHelper辅助类处理相应的回调,并在相应的回调方法中处理动作 3、自定义Behavior要继承CoordinatorLayout.Behavior<V extends View> 4、CoordinatorLayout的直接子类设置layout_behavior属性才有效果(CoordinatorLayout会循环调用每个子view的behavior)
参考:
NestedScrolling机制(一)——概述
http://blog.csdn.net/al4fun/article/details/53888990
源码看CoordinatorLayout.Behavior原理
http://blog.csdn.net/qibin0506/article/details/50377592