我在微信公众号中开间别人推荐的第三方库,看到这枚一个库:该库可以帮你快速实现TabLayout和CoordinatorLayout的组合效果。效果如下:
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写一下想要的效果了。
我这理解的很浅,只是一些表面上的理解,这是我学习之路上的一部分,我会坚持把我学习到的东西总结下来希望对大家起到些作用。
下面粘贴一下源码: