您的位置:首页 > 移动开发 > Android开发

Android CoordinatorLayout和Behavior的源码分析(二)

2017-06-16 18:57 387 查看


2. Behavior如何进行代理的

我们按照以下三种情况分析如何用Behavior进行代理的:

2.1 子view依赖子view状态变化

2.2 嵌套滑动

2.3 Behavior拦截一切事件

具体调用Behavior的方法对应如下:

2.1
public boolean layoutDependsOn(CoordinatorLayout parent, V child, View dependency) {
return false;
}

public boolean onDependentViewChanged(CoordinatorLayout parent, V child, View dependency) {
return false;
}


2.2
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout,
V child, View directTargetChild, View target, int nestedScrollAxes) {
return false;
}
public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, V child, View target,
int dx, int dy, int[] consumed) {
// Do nothing
}
public boolean onNestedFling(CoordinatorLayout coordinatorLayout, V child, View target,
float velocityX, float velocityY, boolean consumed) {
return false;
}


2.3
public boolean onInterceptTouchEvent(CoordinatorLayout parent, V child, MotionEvent ev) {
return false;
}
public boolean onTouchEvent(CoordinatorLayout parent, V child, MotionEvent ev) {
return false;
}


2.1
layoutDependsOn和OndependentViewChanged调用过程

一个view随着另一个view的拖动向反方向移动这种效果,是通过重写Behavior的下面两个方法实现的:
@Override
public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
return dependency instanceof TempView;
}

@Override
public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
int top = dependency.getTop();
int left = dependency.getLeft();
int x = width - left - child.getWidth();
int y = top;
setPosition(child, x, y);
return true;
}

private void setPosition(View v, int x, int y) {
CoordinatorLayout.MarginLayoutParams layoutParams = (CoordinatorLayout.MarginLayoutParams) v.getLayoutParams();
layoutParams.leftMargin = x;
layoutParams.topMargin = y;
v.setLayoutParams(layoutParams);
}


那我看下为什么实现layoutDependsOn和OndependentViewChanged是怎么被调用的:
View.measure
CoordinatorLayout.onMeasure
CoordinatorLayout.ensurePreDrawListener
CoordinatorLayout.hasDependencies
CoordinatorLayout.addPreDrawListener
CoordinatorLayout.dispatchOnDependentViewChanged
CoordinatorLayout$LayoutParams.dependsOn
Dependent2Behavior.layoutDependsOn


我们详细看下dispatchOnDependentViewChanged方法:
void dispatchOnDependentViewChanged(final boolean fromNestedScroll) {
...
// Update any behavior-dependent views for the change
for (int j = i + 1; j < childCount; j++) {
....
if (b != null && b.layoutDependsOn(this, checkChild, child)) {
...
final boolean handled = b.onDependentViewChanged(this, checkChild, child);
....

}
}
}


每次重绘时,dispatchOnDependentViewChanged会判断是否依赖,如果依赖,就去根据自己的需要,对child进行移动或者其他处理。


2.2
onStartNestedScroll和onNestedPreScroll实现原理

父view嵌套子view滑动,上滑时,先滑动父view,子view随着动,向下滑动时,先滑动子view,再滑动父view这种效果的实现,是嵌套滑动,通过重写Behavior的下面的方法实现:
@Override
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) {
return true;
}

@Override
public void onNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
offset(child, dyConsumed);
}

public void offset(View child,int dy){
int old = offsetTotal;
int top = offsetTotal - dy;
top = Math.max(top, -child.getHeight());
top = Math.min(top, 0);
offsetTotal = top;
if (old == offsetTotal){
scrolling = false;
return;
}
int delta = offsetTotal-old;
child.offsetTopAndBottom(delta);
scrolling = true;
}


为了方便理解,我们全面理解一下嵌套滑动机制(NestedScroll)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息