Coordinatorlayout作为协调者布局,主要协调不同的子View测量,布局,向下分发事件和向behavior传递事件,类似于代理模式的代理者。
测量过程: onMeasure()
遍历子View,with = maxUsed , height = maxUsed;
final int width =View.resolveSizeAndState(widthUsed, widthMeasureSpec,childState &View.MEASURED_STATE_MASK);
final int height =View.resolveSizeAndState(heightUsed, heightMeasureSpec,<<View.MEASURED_HEIGHT_STATE_SHIFT);
setMeasuredDimension(width,height); 宽度和高度取最大的使用宽度,这个宽度肯定小于parent的宽度。这样测量的目的在于,子view的测量方式不知道,可能取决于behavior的测量。
布局过程:onLayout()
也是先判断lp.getBehavior()的返回值,如果behavior没有layout设置,则默认从左向右布局。
final Rect out =acquireTempRect();
GravityCompat.apply(resolveGravity(lp.gravity), child.getMeasuredWidth(),
child.getMeasuredHeight(),parent,out, layoutDirection);
child.layout(out.left,out.top,out.right,out.bottom);
事件分发:触摸在AppBarLayout上:
AppBarLayout事件分发1 :在Coordinatorlayout的onTouchevent中,处理。优先判断behavior是否处理。默认AppBarLayout.Behavior如果不拦截,向下传递。
2 : AppBarLayout没有重写OnTouchevent和onInterceptTouchEvent方法,所以默认不处理,继续向上分发给CL
3 : 传给CL的OntouchEvent方法,询问behavior是否处理。HeaderScrollingViewBehavior中的OnTouchevent()返回true,表示处理后续Move事件。 对于AppBarLayout会调用scroll(parent, child, dy, getMaxDragOffset(child), 0),滑动。
4 : ViewTreeObserver.OnPreDrawListener 监听Appbarlayout滚动,然后因为RecyclerView设置了AppBarlayout.ScrollingViewBehavior,就会收到onDependentViewChanged()的调用, offsetChildAsNeeded(child,dependency)调用,recyclerview就跟着滑动了。
事件分发:触摸在RecyclerView上
RecyclerView事件分发1 :在Coordinatorlayout的onTouchevent中处理。优先判断behavior是否处理。默认AppBarLayout.ScrollgingViewBehavior的onInterceptTouchEvent()返回false, 向下传递。
2 : recyclerView分发事件,onInterceptTouchEvent()方法返回false, 继续分发,最终传递给onTouchEvent(),该方法返回true,
后续的Move和Up事件将交给RecyclerView处理。
3 : OnTouchEvent()处理滑动,会通知CL,CL会把再分发给各个子Behavior。比如Appbarlayout.Behavior(),AppBarlayout就会跟着滑动。
4 : RecyclerView的AppBarLayout.ScrollingViewBehavior 可以监听滚动距离等,也会触发onDependentViewChanged()。
总结:Appbarlayout最终处理事件再behavior的OnTouchEvent中,而RecyclerView最终处理在RecyclerView的OnTouchEvent中。
事件都会向上传递给CoordinatorLayout中,然后分发给各个behavior。
网友评论