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

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)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值