官网描述为:CoordinatorLayout 是一个增强版的 FrameLayout(继承自 ViewGroup)
用途:
1、作为应用的顶层视图。
2、作为一个可以指定子 View 之间相互作用的容器,通过给 CoordinatorLayout 的子 View 指定 CoordinatorLayout.Behavior 来定义子 view 之间的相互作用。(你可以想象成:CoordinatorLayout 相当于在两个 View 之间充当中介,这样子的好处就是两个 view 之间的耦合度降低了,只需要跟 coordinatorLayout 打交到即可,而 CoordinatorLayout.Behavior 相当于两个 view 之间的协议,即通过怎样的规则来约束双方的行为。)
设计概念:
- CoordinatorLayout:CoordinatorLayout 作为最顶层视图,将负责管理所有的子 view,使其内部的子 View 彼此间产生一种联系。这个联系通过 Behavior 来实现(包括了滑动状态的处理以及 View 状态的处理)。
- AppBarLayout:AppBarLayout 继承自限性布局,作为增强版的线性布局,他增加了对滑动手势的处理。
- Behavior:Behavior 是 google 新提出的,能够让你以非侵入式的方式去处理目标 View 和其他 View 的交互行为。Behavior 需要设置在触发事件(比如滚动)的 view 上,且这个 View_必须是 CoordinatorLayout 的第一层级下的子 view_,否则没有效果,因为 Behavior 的初始化是在 CoordinatorLayout 的 LayoutParams 中通过反射完成的。
Behavior 实例化方式:1、通过 app:layout_behavior 声明 ;2、在你的自定义 View 类上添加 @DefaultBehavior(MyBehavior.class); - Behavior 只是个接口,其调用是由_NestedScrollingParent 与 NestedScrollingChild 接口负责调用。_
接下来我们通过阅读部分源码进行学习:
首先,我们从两个 view 是如何通过 coordinatorlayout 产生关联来入手;看代码
LayoutParams(Context context, AttributeSet attrs) {
super(context, attrs);
final TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.CoordinatorLayout_Layout);
this.gravity = a.getInteger(
R.styleable.CoordinatorLayout_Layout_android_layout_gravity,
Gravity.NO_GRAVITY);
mAnchorId = a.getResourceId(R.styleable.CoordinatorLayout_Layout_layout_anchor,
View.NO_ID);
this.anchorGravity = a.getInteger(
R.styleable.CoordinatorLayout_Layout_layout_anchorGravity,
Gravity.NO_GRAVITY);
this.keyline = a.getInteger(R.styleable.CoordinatorLayout_Layout_layout_keyline,
-1);
insetEdge = a.getInt(R.styleable.CoordinatorLayout_Layout_layout_insetEdge, 0);
dodgeInsetEdges = a.getInt(
R.styleable.CoordinatorLayout_Layout_layout_dodgeInsetEdges, 0);
mBehaviorResolved = a.hasValue(
R.styleable.CoordinatorLayout_Layout_layout_behavior);
if (mBehaviorResolved) {
mBehavior = parseBehavior(context, attrs, a.getString(
R.styleable.CoordinatorLayout_Layout_layout_behavior));
}
a.recycle();
if (mBehavior != null) {
// If we have a Behavior, dispatch that it has been attached
mBehavior.onAttachedToLayoutParams(this);
}
}
从
mBehaviorResolved = a.hasValue(
R.styleable.CoordinatorLayout_Layout_layout_behavior);
if (mBehaviorResolved) {
mBehavior = parseBehavior(context, attrs, a.getString(
R.styleable.CoordinatorLayout_Layout_layout_behavior));
}
这几句我们可以看到。
mBehaviorResolved 是个 boolean 变量,如果
R.styleable.CoordinatorLayout_Layout_layout_behavior CoordinatorLayout 的
layout_behavior 这个字段设置有值,
1、mBehaviorResolved = true -》调用 parseBehavior 方法,将所需参数传入通过 java 的反射技术返回一个 Behavior 实例。
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,说明当前发生变化的子 view 发生变化时。也就是该方法决定我们用
layout_behavior 标识的 view 是否应该做出相应的变化。默认返回 false,该方法需要我们在创建自己的 Behavior 时重写。
当返回 true 的话,可以看到会调用
b.onDependentViewRemoved(this, checkChild, child);
handled = b.onDependentViewChanged(this, checkChild, child);
为了更好理解这两句代码,我们举个例子,假设有 ViewA 和 ViewB ,当 ViewB 发生移动时,ViewA 要向反方向移动。
1、当 ViewB 被移除时会调用
b.onDependentViewRemoved(this, checkChild, child);
2、当 ViewB 发生变化时,会调用
handled = b.onDependentViewChanged(this, checkChild, child);
那么我们就可以在
b.onDependentViewChanged 里面写我们的功能代码了。
通过以上的分析,希望能帮到大家对 CoordinatorLayout 的协作调用过程有一些些的帮助。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于