Android ConstraintLayout 简介

本文参考:https://juejin.im/post/59c13be46fb9a00a496e5ad1

1.ConstraintLayout定义

Constraint Layout是Google在2016年的Google I/O大会上提出的一个可以灵活控制子控件的位置和大小的新布局。并且其号称可以实现布局最大程度的扁平化。

2.ConstraintLayout优点

1.Constraint Layout可以在不嵌套view group的情况下实现非常庞大、复杂的布局。实现扁平化。
2.Constraint Layout同时具有Relative Layout和Linear Layout的优点、特性。功能强大。
3.使用Constraint Layout来布局时性能要比其他布局方式高。
4.Constraint Layout无论是通过布局管理器拖拽,鼠标控制的形式实现还是使用XML代码去写,都比较方便。

3.ConstraintLayout使用

在app的gralde文件下添加如下代码即可使用:

implementation 'com.android.support.constraint:constraint-layout:1.1.3'
4.ConstraintLayout简介

要在 ConstraintLayout 中定义 View 的位置,必须为该 View 添加至少一个水平和垂直约束(否则该 View 就会在左上角绘制)。该约束对象可以是另一个视图,或者父布局(也就是 ConstraintLayout),或者是不可见的 Guideline,否则编译器会报错。

约束布局中的控件操作可以使用图形化界面完成,但是这样太简单了而且不能精细化操作,所以本文主要用代码使用ConstraintLayout。

在XML文件中添加一个约束布局。

<android.support.constraint.ConstraintLayout 
	xmlns:android="http://schemas.android.com/apk/res/android"
    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">

android.support.constraint.ConstraintLayout>
4.1 Relative positioning

约束的效果和RelativeLayout布局有异曲同工之处,只不过要比RelativeLayout强大。约束能允许我们指定一个控件相对于另一个控件的位置,通过一些属性我们可以对组件进行水平或者垂直排列。例如当我们使用含有Left, Right, Start 或者End关键词词属性进行定位时即是对组件进行水平方向排列,同理 top, bottom 和 text baseline(文字的基线位置)就是垂直方向排列。具体相对定位的一些属性组合如下

layout_constraintLeft_toLeftOf			当前组件的左边与某组件的左边左对齐
layout_constraintLeft_toRightOf			当前组件的左边与某组件的右边对齐
layout_constraintRight_toLeftOf			当前组件的右边与某组件的左边对齐
layout_constraintRight_toRightOf		当前组件的右边与某组件的右边对齐
layout_constraintTop_toTopOf			当前组件的上边与某组件的上边对齐
layout_constraintTop_toBottomOf			当前组件的上边与某组件的下边对齐
layout_constraintBottom_toTopOf			当前组件的下边与某组件的上边对齐
layout_constraintBottom_toBottomOf		当前组件的下边与某组件的下边对齐
layout_constraintBaseline_toBaselineOf	当前组件的基线位置与某组件的基线位置对齐(很少用)
layout_constraintStart_toEndOf			当前组件的开始与某组件的结束对齐
layout_constraintStart_toStartOf		当前组件的开始与某组件的开始对齐
layout_constraintEnd_toStartOf			当前组件的结束与某组件的开始对齐
layout_constraintEnd_toEndOf			当前组件的结束与某组件的结束对齐

对于上面这些属性的值有两种,一种就是同层级组件ID,还有就是parent,当值为parent时即是相对于父布局进行定位。

将一个控件放在视图的中间,这个可以理解从四个方向都又拉力,把这个控件拉到了中间。

<Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Test"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

Android ConstraintLayout 简介_第1张图片
使用约束布局进行约束,让两个控件相互挨着。

<Button
        android:id="@+id/test1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@color/colorAccent"
        android:text="Test1"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/test2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary"
        android:text="Test2"
        app:layout_constraintLeft_toRightOf="@id/test1"
        app:layout_constraintTop_toTopOf="parent" />

在这里插入图片描述
但是如果将test2的

app:layout_constraintTop_toTopOf="parent"

改为

app:layout_constraintTop_toBottomOf="@id/test1"

会发生这样的效果,因为这个属性代表test2的顶部与test1的底部对齐。

Android ConstraintLayout 简介_第2张图片
如果将test2改成这样,又会发生新的变化,怎么样,是不是感觉很灵活,也很方便。

<Button
        android:id="@+id/test2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary"
        android:text="Test2"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

Android ConstraintLayout 简介_第3张图片

4.2 Margins

对于margin值我们都很熟悉,因为在其它的布局中我们也经常使用,可分为以下几种

android:layout_marginStart
android:layout_marginEnd
android:layout_marginLeft
android:layout_marginTop
android:layout_marginRight
android:layout_marginBottom

但是在ConstraintLayout布局中不同的是,margin只对设置了约束的地方起作用。
ConstraintLayout还添加了一些属性,即layout_goneMargin**类的属性,该属性是表示约束隐藏时的margin值,例如给上面的textView2我们增加app:layout_goneMarginLeft="100dp"属性,当约束textView1隐藏时就可以保持textview2位置不变。

需要注意的一点是如果某个约束设置了View.GONE,相当于这个组件宽和高为0,约束布局中相当于一个点,其他设置的约束依然有效。

4.3 Centering positioning and bias

在约束布局中还提供了bias,通过属性layout_constraintHorizontal_bias或者layout_constraintVertical_bias设置组件偏向水平或者垂直的某一侧,默认情况下该值是0.5(50%)。数字越小越靠近左上,越大越靠近右下。

<Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Test"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintHorizontal_bias="0.3"
        app:layout_constraintVertical_bias="0.7"/>

Android ConstraintLayout 简介_第4张图片

4.4 Dimensions constraints

当我们的约束布局的子组件设置wrap_content时,我们可以通过android:minWidth或者android:minHeight 属性设置最小宽度或者高度的约束。minWidth/minHeight只有宽度或者高度为wrap_content才有作用。

对于android:layout_height /android:layout_width属性,它的值只有三种情况
1.使用指定的大小或者指定大小的引用,如100dp
2.WRAP_CONTENT,此时根据内容自己计算大小
3.0dp,该值相当于MATCH_CONSTRAINT。

在上面的TextView我们设置layout_width分别是100dp,0dp,0dp(marginLeft :20dp)效果如图a,b,c
Android ConstraintLayout 简介_第5张图片

4.5 Ratio

比例约束可以约束我们控件的宽高比,例如下面示例

<TextView
        android:id="@+id/textView1"
        android:layout_width="100dp"
        android:layout_height="0dp"
        android:background="@color/colorAccent"
        android:gravity="center"
        android:text="textView1"
        app:layout_constraintDimensionRatio="2:1"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent" />

设置宽度为100dp,高度为0dp,此时设置了宽高比是2:1,则宽度会自动约束调整为50dp。如果我们将上面的宽和高度调换,宽为0dp,高100dp,此时最终宽度为200,高度100(宽:高=2:1)

在上面介绍的的宽高比约束是单维度的,那么如果我们的宽和高都有约束,都设置为0dp,在这种情况下,系统会使用满足所有约束条件和比率的最大尺寸。当然我们也可以在比例值前面加 W 或者 H 来分别约束宽度或者高度,如H,2:1。

4.6 Chains

链是一种特殊的约束,它能让该链连接的多个Views 平分剩余空间位置。

<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    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">

    <TextView
        android:id="@+id/A"
        android:layout_width="100dp"
        android:layout_height="30dp"
        android:background="@color/colorPrimary"
        android:gravity="center"
        android:text="A"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/B"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/B"
        android:layout_width="100dp"
        android:layout_height="30dp"
        android:background="@color/colorAccent"
        android:gravity="center"
        android:text="B"
        app:layout_constraintLeft_toRightOf="@+id/A"
        app:layout_constraintRight_toLeftOf="@+id/C"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/C"
        android:layout_width="100dp"
        android:layout_height="30dp"
        android:background="@color/colorPrimaryDark"
        android:gravity="center"
        android:text="C"
        app:layout_constraintLeft_toRightOf="@+id/B"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

上面代码的效果图如下,A和C相对于父组件的左边和右边有一个约束,A和B,B和C之间两两相互约束,我们还需要知道的是对我们称链的第一个元素组件为链头。如下图A就是该链的链头
Android ConstraintLayout 简介_第6张图片
对于链头我们可以通过属性layout_constraintHorizontal_chainStyle(layout_constraintVertical_chainStyle)设置,该属性有三个值,spread ,spread_inside ,packed
1.CHAIN_SPREAD:默认情况下该属性默认值是spread 。它的间隙将平分剩余空间,如上图所示
2.CHAIN_SPREAD_INSIDE:spread_inside值会把两边最边缘的两个 View 靠边显示,然后让剩余的 Views 在剩余的空间内平分间隙。当面设置spread_inside时效果图如下
Android ConstraintLayout 简介_第7张图片
3.CHAIN_PACKED:还有一种值是packed ,它表示将view之间紧挨着显示,并且全体居中显示,设置该模式后效果图如下
Android ConstraintLayout 简介_第8张图片
除此之外,我们可以通过设置layout_constraintHorizontal_bias属性来调整整体的位置。默认情况居中,也就是该值为0.5,例如我们将该值设置0.3,则实现效果如下:
Android ConstraintLayout 简介_第9张图片
在官方文档中还介绍了一种模式是权重模式,在CHAIN_SPREAD 模式中,如果我们设置控件的宽或者高设置MATCH_CONSTRAINT即0dp,它们将按权重平分占满父控件的宽或者高,对于权重的设置是属性和我们线性布局设置权重达到一样的效果,例如在上面的三个TextView,我们设置宽度都为0dp,并设置链样式为spread(或spread_inside),此时效果图如下
Android ConstraintLayout 简介_第10张图片
如果我们给A和C设置下面属性

        app:layout_constraintHorizontal_weight="1"

给B设置属性

       app:layout_constraintHorizontal_weight="2"

复制代码那么此时A,B,C的宽度为1:2:1比例占满父组件宽度。设置权重时链样式不能设置为packed (设置后宽度会收缩为0)

4.7 Guideline

Guideline用于辅助我们对View进行定位,以及设置约束,它不会再真正的显示,只是起到辅助作用,常用属性如下:
1.android:orientation 该属性可以指定辅助线是垂直还是水平线,它有两个值即vertical,horizontal,
2.layout_constraintGuide_begin/layout_constraintGuide_end 用来设置对齐父组件的 start 或者end边缘的距离,
3.layout_constraintGuide_percent 该值是0.0到1.0之间,用来设置辅助线在父布局的位置,例如设置0.5,就相当于在父视图宽度的中间50%。

<android.support.constraint.Guideline
      android:id="@+id/guideline_h"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:orientation="horizontal"
      app:layout_constraintGuide_percent="0.5" />

  <android.support.constraint.Guideline
      android:id="@+id/guideline_v"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:orientation="vertical"
      app:layout_constraintGuide_percent="0.5" />

  <TextView
      android:id="@+id/tvguide"
      android:layout_width="50dp"
      android:layout_height="50dp"
      android:background="@color/red"
      android:gravity="center"
      android:text="Guide"
      app:layout_constraintBottom_toTopOf="@+id/guideline_h"
      app:layout_constraintLeft_toLeftOf="@+id/guideline_v" />

在上面我们在约束布局中创建两个辅助线,分别是垂直和水平的辅助线,并将textView的下面和水平辅助线的上面对齐,将TextView的左边和垂直辅助线左边对齐。这样我们可以使用辅助线任意控制View的约束位置。

Android ConstraintLayout 简介_第11张图片

你可能感兴趣的:(Android)