Android Material Design 中的CorrdinatorLayout使用详解

转发请备注原文地址:https://www.niwoxuexi.com/blog/android/article/191.html
我在找了一些关于CoordinatorLayout
的教程,大部分文章都是讲解把CoordinatorLayout, AppbarLayout ,CollapsingToolbarLayout以及Toolbar 等缓和一起使用,这很容易是大家混淆,不知道如何利用CoordinatorLayout使用到不同的场景中。其实CoordinatorLayout的功能并不是局限于与AppBarLayout一起使用,它的功能非常强大,本文将针对CoordinatorLayout的使用进行详细介绍,在后面再介绍将AppBarLayout和CollapsingToolBarLayout整合CoordinatorLayout一起。那么到底CoordinatorLayout是如何使用的呢,那就听我细细道来吧~
CoordinatorLayout 到底是什么,能干什么?
先看一下官方的描述吧:
CoordinatorLayout is a super-powered FrameLayout
.
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是一个超级的FrameLayout 布局,它的作用是帮助我们协调它的个个子View的布局,我们先看一个案例动画组:


稍微解释一下这个动画:小面的绿色小球是一个普通的View,上面的飞机是一个ImageView ,我们水平拖动小球,飞机向相反的方向运动;垂直方向拖动小球会跟着相
同的方向运动;
简而言之:水平方向反向运动,垂直方向同向运动;
这个例子就是运用CoordinatorLayout实现的,当然让你不用CoordinatorLayout
去实现,应该没有任何问题,但是代码的耦合度应该非常大,你的代码必须要持有
2个View的引用,然后在onTouchEvent里面做各种判断和逻辑处理,这耦合度未免太伤人伤力了~
而CoordinatorLayout既然号称能帮我们协调子View的布局,我们接下来看看CoordinatorLayout如何实现~

CoordinatorLayout 的使用

CoordinatorLayout的使用核心是Behavior,Behavior就是执行你定制的动作。
看先Behavior的官方解释吧:


Interaction behavior plugin for child views of CoordinatorLayout.

翻译:Behavior就是用来给CoordinatorLayout的子view们实现交互的。
在讲Behavior之前必须先理解两个概念:Child和Dependency,什么意思呢?Child当然是子View的意思了,是谁的子View呢,当然是CoordinatorLayout的子View;其
实Child是指要执行动作的CoordinatorLayout的子View。而Dependency是指Child依赖的View。比如上面的gif图中,绿色的小球的View就是Dependency,上面的小飞机的ImgeView就是Child,上面小飞机的动作是依赖下面的绿色的View。简而言之,就是如过Dependency这个View发生了变化,那么Child这个View就要相应发生变化。发生变化是具体发生什么变化呢?这里就要引入Behavior,Child发生变化的具体执行的代码都是放在Behavior这个类里面。
怎么使用Behavior呢,首先,我们定义一个类,继承CoordinatorLayout.Behavior,其中,泛型参数T是我们要执行动作的View类,也就是Child。然后就是去实现
Behavior的两个方法:

/**

  • 判断child的布局是否依赖dependency
    /
    @Override
    public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
    //返回false表示child不依赖dependency,ture表示依赖
    return true;
    }
    /
    *
  • 当dependency发生改变时(位置、宽高等),执行这个函数
  • 返回true表示child的位置或者是宽高要发生改变,否则就返回false
    */
    @Override
    public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
    //根据dependency的位置,设置child的位置
    return true;
    }

看了上面的概念后,我们看看具体怎么去实现吧~
为了响应跟随手指移动的操作,我们定义一个非常简单的View,这个View只响应跟随手指移动,将这个View作为Dependency。由于过于简单,这个View源码不粘贴,我们只需知道这个View的类名叫:DependentView。

先看一下:Behavior的实现:


package com.niwoxuexi.coordinatelayout;
import android.content.Context;
import android.support.design.widget.CoordinatorLayout;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.View;
/**

  • Created by zhuxiaocheng on 2017/7/6.
    /
    public class MyBehavior extends CoordinatorLayout.Behavior {
    private int screenWidth;
    public MyBehavior(Context context, AttributeSet attrs) {
    super(context, attrs);
    DisplayMetrics display = context.getResources().getDisplayMetrics();
    screenWidth = display.widthPixels;
    }
    /
    *
    • 判断child的布局是否依赖dependency
      /
      @Override
      public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
      //返回false表示child不依赖dependency,ture表示依赖
      return true;
      }
      /
      *
    • 当dependency发生改变时(位置、宽高等),执行这个函数
    • 返回true表示child的位置或者是宽高要发生改变,否则就返回false
      /
      @Override
      public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
      //根据dependency的位置,设置child的位置
      int top = dependency.getTop();
      int left = dependency.getLeft();
      int x = screenWidth - left - child.getWidth();
      int y = top - 800;
      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);
      }
      }

再看一下DependentView的实现:

package com.niwoxuexi.coordinatelayout;
import android.content.Context;
import android.support.design.widget.CoordinatorLayout;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.View;
/
*
  • Created by zhuxiaocheng on 2017/7/6.
    /
    public class MyBehavior extends CoordinatorLayout.Behavior {
    private int screenWidth;
    public MyBehavior(Context context, AttributeSet attrs) {
    super(context, attrs);
    DisplayMetrics display = context.getResources().getDisplayMetrics();
    screenWidth = display.widthPixels;
    }
    /
    *
    • 判断child的布局是否依赖dependency
      /
      @Override
      public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
      //返回false表示child不依赖dependency,ture表示依赖
      return true;
      }
      /
      *
    • 当dependency发生改变时(位置、宽高等),执行这个函数
    • 返回true表示child的位置或者是宽高要发生改变,否则就返回false
      */
      @Override
      public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
      //根据dependency的位置,设置child的位置
      int top = dependency.getTop();
      int left = dependency.getLeft();
      int x = screenWidth - left - child.getWidth();
      int y = top - 800;
      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);
      }
      }

  • OK,现在我们有了Dependency 的控件DependentView,并且定义好了跟随Dependency一直变化的动作(Behavior)MyBehavior,接下来我们就要指定好为哪个具体的ImageView实例来绑定这些。
    **方法灰常简单,直接布局文件指定就好:******

    app:layout_behavior="com.niwoxuexi.coordinatelayout.MyBehavior"
    直接上代码,大家自己体会吧



    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.niwoxuexi.coordinatelayout.MainActivity">
    android:layout_width="50dp"
    android:layout_height="50dp"
    android:src="@drawable/plane"
    android:scaleType="fitCenter"
    android:layout_marginLeft="180dp"
    android:layout_marginTop="100dp"
    app:layout_behavior="com.niwoxuexi.coordinatelayout.MyBehavior"
    />
    android:layout_width="50dp"
    android:layout_height="50dp"
    android:background="@drawable/button"
    android:layout_marginLeft="180dp"
    android:layout_marginTop="460dp" />


    是不是很简单呢?我们只需关注Behavior的编写就好了,把Child和Dependency之间的在xml文件中设置就可以了~
    最后是上代码时间喽:https://image.niwoxuexi.com/blog/downloadCoordinateLayout.zip

    你可能感兴趣的:(Android Material Design 中的CorrdinatorLayout使用详解)