一、CoordinatorLayout简介

java.lang.Object   ↳    android.view.View       ↳    android.view.ViewGroup           ↳    android.support.design.widget.CoordinatorLayout 

实现了NestedScrollingParent接口,CoordinatorLayout, NestedScrollView, SwipeRefreshLayout都实现了这个接口

CoordinatorLayout is a super-powered FrameLayout. 所以属性和FrameLayout有点像

CoordinatorLayout 控件是design下最重要的一个控件,也是最复杂、功能最强大的,这从他的作用就可以看的出来

二、CoordinatorLayout作用

CoordinatorLayout is intended for two primary use cases:

  • As a top-level application decor or chrome layout
  • As a container for a specific interaction with one or more child views

上面是官方给的解释,CoordinatorLayout的作用就两个:

  • 作为一个最顶层根布局因为CoordinatorLayout本身就是继承ViewGroup
  • 作为一个容器协调子View的行为(通过CoordinatorLayout.Behavior)

所以这里最重要就是这个Behavior了,如果你完全掌握了Behavior,CoordinatorLayout就搞定了

三、CoordinatorLayout.Behavior研究

public static abstract class Behavior<V extends View>

查看CoordinatorLayout的源码我们可以看到这是一个抽象类,里面定义了很多方法,如果需要使用我们要继承CoordinatorLayout.Behavior然后重新一些方法。

我们拿AppBarLayout为例,AppBarLayout中有两个Behavior,一个是拿来给它自己用的,另一个是拿来给它的兄弟结点用的,我们重点关注下AppBarLayout.ScrollingViewBehavior这个类。

我们用到的appbar_scrolling_view_behavior指的也是AppBarLayout.ScrollingViewBehavior这个类

 app:layout_behavior="@string/appbar_scrolling_view_behavior"

通过查看ScrollingViewBehavior也是继承CoordinatorLayout.Behavior

java.lang.Object   ↳    android.support.design.widget.CoordinatorLayout.Behavior.view.View>       ↳    android.support.design.widget.AppBarLayout.ScrollingViewBehavior 

我们看看CoordinatorLayout.Behavior类中的以下方法

1、layoutDependsOn

 @Override public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {       //如果dependency是AppBarLayout的实例,说明它就是我们所需要的Dependency       return dependency instanceof AppBarLayout; }

这个方法告诉CoordinatorLayout,这个view是依赖AppBarLayout的,后续父亲可以利用这个方法,查找到这个child所有依赖的兄弟结点。在CoordinatorLayout.Behavior直接return false;

2、onDependentViewChanged

 //每次dependency位置发生变化,都会执行onDependentViewChanged方法 @Override public boolean onDependentViewChanged(CoordinatorLayout parent, View child,        View dependency) {        return false; }

这个方法,可以在这个回调中记录dependency的一些位置信息,在onLayoutChild中利用保存下来的信息进行计算,然后得到自身的具体位置。

3、onLayoutChild

 public boolean onLayoutChild(CoordinatorLayout parent, V child, int layoutDirection) {            return false;        }

这个方法是用来子view用来布局自身使用,如果依赖其他view,那么系统会首先调用

4、onMeasureChild

public boolean onMeasureChild(CoordinatorLayout parent, V child,                int parentWidthMeasureSpec, int widthUsed,                int parentHeightMeasureSpec, int heightUsed) {            return false;        }

这个是CoordinatorLayout在进行measure的过程中,利用Behavior对象对子view进行大小测量的一个方法。
在这个方法内,我们可以通过parent.getDependencies(child);这个方法,获取到这个child依赖的view,然后通过获取这个child依赖的view的大小来决定自身的大小。

5、NestedScroll

 public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout,                V child, View directTargetChild, View target, int nestedScrollAxes) {            return false;        } public void onNestedScrollAccepted(CoordinatorLayout coordinatorLayout, V child,                View directTargetChild, View target, int nestedScrollAxes) {            // Do nothing        }   public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, V child, View target) {            // Do nothing        } public void onNestedScroll(CoordinatorLayout coordinatorLayout, V child, View target,                int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {            // Do nothing        }    

这几个方法刚好是NestedScrollingParent的方法(CoodinatorLayout是继承了NestedScrollingParent的),也就是对CoodinatorLayout进行的一个代理(Proxy),即CoordinatorLayout自己不对这些消息进行处理,而是传递给子view的Behavior,进行处理。利用这样的方法,实现了view和view之间的交互和视觉的协同(布局、滑动)。
有兴趣可以看 鸿 洋大神的NestedScrolling机制完全解析:
Android NestedScrolling机制完全解析 带你玩转嵌套滑动

四、自定义Behavior

实现如下红色button,高度保持跟蓝色View一样,x轴方向相反
Android Material Design之CoordinatorLayout_第1张图片

构造方法

 public MyBehavior(Context context, AttributeSet attrs) {        super(context, attrs);        DisplayMetrics display = context.getResources().getDisplayMetrics();        width = display.widthPixels;    }

一定要重写这个构造函数。因为CoordinatorLayout源码中parseBehavior()函数中直接反射调用这个构造函数。

static final Class<?>[] CONSTRUCTOR_PARAMS = new Class<?>[] {        Context.class,        AttributeSet.class};

然后我们实现layoutDependsOn、onDependentViewChanged方法,自定义Behavior就完成了

下面是MyBehavior 的源码

public class MyBehavior extends CoordinatorLayout.Behavior<Button> {    private int width;    public MyBehavior(Context context, AttributeSet attrs) {        super(context, attrs);        DisplayMetrics display = context.getResources().getDisplayMetrics();        width = display.widthPixels;    }    @Override    public boolean layoutDependsOn(CoordinatorLayout parent, Button child, View dependency) {        //如果dependency是TempView的实例,说明它就是我们所需要的Dependency        return dependency instanceof FollowView;    }    //每次dependency位置发生变化,都会执行onDependentViewChanged方法    @Override    public boolean onDependentViewChanged(CoordinatorLayout parent, Button child, View dependency) {        //根据dependency的位置,设置Button的位置        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);    }}

项目源码

https://github.com/Yi520153/DesignCoordinatorLayout

总结

可以看到CoodinatorLayout给我们实现了一个可以被子view代理实现方法的一个布局。这和传统的ViewGroup不同,子view从此知道了彼此之间的存在,一个子view的变化可以通知到另一个子view。CoordinatorLayout所做的事情就是当成一个通信的桥梁,连接不同的view。使用Behavior对象进行通信。

参考资料

CoordinatorLayout的使用如此简单
关于CoordinatorLayout与Behavior的一点分析
CoordinatorLayout布局的使用方式
CoordinatorLayout与滚动的处理
Android Support Design 中 CoordinatorLayout 与 Behaviors 初探

更多相关文章

  1. Android 打开浏览器的几种方法
  2. 关于"match_parent"这个xml的布局设定值
  3. Android中hardware源码(android-5.0.2)
  4. android 源码
  5. 引入布局
  6. Android中RelativeLayout布局各个xml相对布局属性的介绍和使用
  7. Unity调用Android配置方法
  8. Android 滑动手势侦测方法介绍
  9. Android之TableLayout布局

随机推荐

  1. 使用Android(安卓)adb命令来启动Android
  2. 我的android 第一天-电话拨号器
  3. Android:shape的使用详解(1)
  4. android的binder机制研究二
  5. Android(安卓)中级教程之------Android(
  6. Android、iOS系统架构
  7. android 上 webkit js 扩展之全局本地对
  8. Android(安卓)安全机制概述 Permission
  9. Android的消息处理机制(深入源码)
  10. android EditText inputType 及 android: