美文网首页
关于CoordinatorLayout.behavior 学习

关于CoordinatorLayout.behavior 学习

作者: SoLix | 来源:发表于2017-02-22 18:25 被阅读0次


我在微信公众号中开间别人推荐的第三方库,看到这枚一个库:该库可以帮你快速实现TabLayout和CoordinatorLayout的组合效果。效果如下:

图1

Github地址:https://github.com/hugeterry/CoordinatorTabLayout

       看到这个库我就想在自己的demo中试一下,看到介绍是使用CoordinatorLayout 实现的我就在网上搜了文章看看,之后看到别人的总结(附上链接http://blog.csdn.net/huachao1001/article/details/51554608),是关于 CoordinatorLayout.Behavior的使用,效果图不好弄出来,就简单说一下:就是在CoordinatorLayout布局中拖动一个button 另一个button随之移动,这个感觉很好实现,但是耦合会很大,上面的链接中就介绍了用CoordinatorLayout.Behavior怎么实现,先去看完上面的链接讲解再回来看接下的内容。

       最后我有个疑问就是:button 添加了app:layout_behavior="com.hc.studyCoordinatorLayout.MyBehavior"之后怎么跟着tempView随之移动的,tempView 中没有添加任何的监听等多余的代码???但是效果真的出来了,跟着这个疑问我就点开了CoordinatorLayout.Behavior的源码看看是怎么实现的:在MyBehavior这个类中有这个方法layoutDependsOn,只有这个方法与tempView有关联,我们来看下你父类中对这个方法的解释:

/**

* Determine whether the supplied child view has another specific sibling view as a

* layout dependency.

*

This method will be called at least once in response to a layout request. If it

* returns true for a given child and dependency view pair, the parent CoordinatorLayout

* will:

*

Always lay out this child after the dependent child is laid out, regardless

* of child order.

*

Call {@link #onDependentViewChanged} when the dependency view's layout or

* position changes.

*

* @param parent the parent view of the given child

* @param child the child view to test

* @param dependency the proposed dependency of child

* @return true if child's layout depends on the proposed dependency's layout,

* false otherwise

* @see #onDependentViewChanged(CoordinatorLayout, android.view.View, android.view.View)

*/

public boolean layoutDependsOn(CoordinatorLayout parent, V child, View dependency) {

return false;

}

意思是:确定提供子视图还有另一个特定的兄弟视图布局的依赖。

此方法将响应布局请求至少调用一次。 如果它

对给定的子视图和依赖视图对返回true,父CoordinatorLayout将:

总是把这个孩子依赖孩子,不管孩子的秩序。

当依赖布局位置大小改变的时候调用;

/**

* Check if an associated child view depends on another child view of the CoordinatorLayout.

*

* @param parent the parent CoordinatorLayout

* @param child the child to check

* @param dependency the proposed dependency to check

* @return true if child depends on dependency

*/

boolean dependsOn(CoordinatorLayout parent, View child, View dependency) {

return dependency == mAnchorDirectChild

|| (mBehavior != null && mBehavior.layoutDependsOn(parent, child, dependency));

}

在CoordinatorLayout布局中检查子视图依赖另一个子视图;

/**

* Check if the given child has any layout dependencies on other child views.

*/

boolean hasDependencies(View child) {

final LayoutParams lp = (LayoutParams) child.getLayoutParams();

if (lp.mAnchorView != null) {

return true;

}

final int childCount = getChildCount();

for (int i = 0; i < childCount; i++) {

final View other = getChildAt(i);

if (other == child) {

continue;

}

if (lp.dependsOn(this, child, other)) {

return true;

}

}

return false;

}

就是循环查看子视图依赖另一个子视图;在上面的源码中我们可以知道通过循环来检查视图的依赖关系;

好到这里我们就可以总结一下它的实现原理了:

        首先我们自定义的MyBehavior 继承了CoordinatorLayout.Behavior类,并重写这个抽象类的两个方法layoutDependsOn和onDependentViewChanged,layoutDependsOn是判断CoordinatorLayout下的子视图是否其中一个子视图依赖另一个子视图,onDependentViewChanged 是当被依赖的子视图发生改变了都会执行这个方法。

        我们从layoutDependsOn看起,找到CoordinatorLayout.Behavior 中的layoutDependsOn方法,在整个类中查找哪里调用了layoutDependsOn方法,这个调用过程是:onMeasure方法第二行调用了ensurePreDrawListener方法,ensurePreDrawListener方法里通过循环遍历CoordinatorLayout的每个子视图并调用hasDependencies方法来判断CoordinatorLayout下的子视图是否有依赖关系的,如果有在ensurePreDrawListener中调用addPreDrawLinstener方法添加依赖监听,在addPreDrawLinstener方法中给ViewTreeObserver添加监听(创建的OnPreDrawLintener),OnPreDrawLintener这个类实现ViewTreeObserver.OnpreDrawListener接口,并在实现的onPredraw方法中调用DispatchOnDepentViewChanged方法,DispatchOnDepentViewChanged这个方法就是前面说的CoordinatorLayout.Behavior中的一个方法用于当被依赖的子视图发生改变了都会执行这个方法;

         看到这里我们就对CoordinatorLayout.Behavior有了一个大致的了解之后我们就可以用CoordinatorLayout.Behavior写一下想要的效果了。

        我这理解的很浅,只是一些表面上的理解,这是我学习之路上的一部分,我会坚持把我学习到的东西总结下来希望对大家起到些作用。

下面粘贴一下源码:

图2 图3 图4 图5 图6

相关文章

网友评论

      本文标题:关于CoordinatorLayout.behavior 学习

      本文链接:https://www.haomeiwen.com/subject/tfvmwttx.html