1.文章内容概述
本文主要是针对Behavior的运作机制,通过对CoordinatorLayout的源码中对此Behavior的执行过程进行分析,得出其运行原理。本文主要是针对behavior的layout child的方式,touch事件的处理,以及内嵌滑动事件的处理进行重要分析。
2.阅读本文前的准备工作
关于内嵌滑动,这是在android5.0之后google提出的,并且在support包也包含,主要是支持内嵌滑动的控件支持内嵌滑动。也就是实现了NestedScrollingParent,NestedScrollingChild这两个接口的view支持。
了解内嵌滑动的执行原理,可以查看这篇文章:http://blog.youkuaiyun.com/chen930724/article/details/50307193 ,但是没有对 onNestedPreScroll() 和onNestedScroll()进行更加深刻的分析,但是本人通过对系统中实现了NestedScrollingChild接口的两个view(NestedSrcoller和RecyclerView)进行源码解析,得出如下结论:
/**
* 此方法是在 子nestedview的 onTouchEvent()方法的 Move事件 中被调用的( 通过查看NestedScrollView 和 RecyclerView得知)
* 只要执行到 子 nestedview的 onTouchEvent()就会执行到此方法
* 注意:如果此方法将dx 和 dy 全都消耗完了,那么 子nested view 就不能处理移动事件了,因为 当前父nested view(这里是 behavior,他是在 CoordinatorLayout的回调函数中调用的)
* 已经将全部的touch move事件全部消耗完了
* @param coordinatorLayout
* @param child 当前behavior所在的view
* @param target 当前nestedscroll 的child的view (正在内嵌滑动的view)
* @param dx
* @param dy
* @param consumed
*/
@Override
public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dx, int dy, int[] consumed) {
super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed);
}
/**
* 此方法也是在 子nestedView 的 onTouchEvent()方法中的 Move事件 中被调用,但是它是在上面的方法的后面调用,并且调用是有条件的.(得知同上)
* 条件: 当前move移动的距离 减去 consumed消耗的距离,如果小于 touchSlop ,那么就不会执行到这个方法,否则才会执行到这个方法
* 注意: 这里 dxConsumed和 dyConsumed 和上面那个方法的consumed消耗的距离是没有任何关系的.这个方法的x,y消耗的值是上面的pre方法执行完之后,当前child view移动的距离,
* 而dxUnconsumed 和 dyUnconsumed 是 move事件移动的距离减去 上面pre方法消耗的距离之后的 数值,减去本方法的dxConsumed和dyConsumed的值.
* @param coordinatorLayout
* @param child
* @param target
* @param dxConsumed
* @param dyConsumed
* @param dxUnconsumed
* @param dyUnconsumed
*/
@Override
public void onNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
}
3.CoordinatorLayout源码解析
首先,Behavior的创建,因为Behavior是存在CoordinatorLayout中的LayoutParams的mBehavior的变量,并且实例化是在LayoutParams的构造函数中进行初始化的。代码如下所示:
LayoutParams(Context context, AttributeSet attrs) {
.......
if (mBehaviorResolved) {
mBehavior = parseBehavior(context, attrs, a.getString(
R.styleable.CoordinatorLayout_LayoutParams_layout_behavior));