新布局ConstraintLayout


引言

ConstraintLayout是Google在2016的Goodle I/O大会时提出的,目前的稳定版本是1.0.2,它可以降低布局的嵌套层级,提升页面渲染。

参考文章:

1.几种属性介绍

1.2 相对位置

  • 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
    设置两个空间之间的 文字相对于baseline对齐
  • layout_constraintStart_toEndOf
  • layout_constraintStart_toStartOf
  • layout_constraintEnd_toStartOf
  • layout_constraintEnd_toEndOf

效果图:


布局文件

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_relative_position"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button
        android:id="@+id/btn_A"
        android:text="A"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        style="@style/Constraint_style"/>
    <Button
        style="@style/Constraint_style"
        android:text="在A上方,与A居中对齐"
        app:layout_constraintLeft_toLeftOf="@id/btn_A"
        app:layout_constraintRight_toRightOf="@id/btn_A"
        android:layout_marginBottom="40dp"
        app:layout_constraintBottom_toTopOf="@id/btn_A"/>
    <Button
        style="@style/Constraint_style"
        android:text="平居中对齐"
        android:layout_width="wrap_content"
        android:layout_height="80dp"
        android:layout_marginLeft="10dp"
        app:layout_constraintLeft_toRightOf="@id/btn_A"
        app:layout_constraintTop_toTopOf="@id/btn_A"
        app:layout_constraintBottom_toBottomOf="@id/btn_A"/>
    <Button
        style="@style/Constraint_style"
        android:text="在A下方,与A左对齐"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="@id/btn_A"
        app:layout_constraintTop_toBottomOf="@id/btn_A"
        android:layout_marginTop="100dp"/>
    <Button
        style="@style/Constraint_style"
        android:text="在A下方,与A右对齐"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintRight_toRightOf="@id/btn_A"
        app:layout_constraintTop_toBottomOf="@id/btn_A"
        android:layout_marginTop="25dp"/>
    <Button
        style="@style/Constraint_style"
        android:text="BASELINE对齐"
        android:layout_width="wrap_content"
        android:layout_height="80dp"
        android:gravity="bottom"
        app:layout_constraintLeft_toLeftOf="parent"
        android:layout_marginLeft="10dp"
        app:layout_constraintBaseline_toBaselineOf="@id/btn_A"/>


</android.support.constraint.ConstraintLayout>

1.3 边距

在ConstrainLayout中,控件除了可以设置普通的边距属性,还可以设置当空间依赖的控件GONE之后的边距属性。下面是依赖控件GONE之后的边距属性:

  • layout_goneMarginStart
  • layout_goneMarginEnd
  • layout_goneMarginLeft
  • layout_goneMarginTop
  • layout_goneMarginRight
  • layout_goneMarginBottom

需求:B控件依赖A,A距离父容器左边20dp,B在A右边,距离A为20dp。需求当A设置为GONE之后,B距离父容器左边60dp。

A在gone之前的效果图:


<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_margin"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button
        style="@style/Constraint_style"
        android:id="@+id/btn_a"
        android:text="A"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_marginTop="100dp"
        />

    <Button
        style="@style/Constraint_style"
        android:text="B"
        android:textAllCaps="false"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toRightOf="@id/btn_a"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_marginLeft="20dp"
        app:layout_goneMarginLeft="60dp"
        android:layout_marginTop="100dp"
        />

</android.support.constraint.ConstraintLayout>

A在gone之后的效果图:


1.3 偏移

控件设置居中(包括水平居中、垂直居中、水平垂直居中)属性之后,通过偏移属性可以设置染空间更偏向于依赖控件的某一方,偏移值设置为0-1之间的值。

  • layout_constraintHorizontal_bias
    水平偏移
  • layout_constraintVertical_bias
    垂直偏移

效果图:


布局文件:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_margin"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button
        style="@style/Constraint_style"
        android:id="@+id/btn_a"
        android:text="水平偏移30%"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintHorizontal_bias="0.3"
        />

    <Button
        style="@style/Constraint_style"
        android:text="垂直偏移30%"
        android:textAllCaps="false"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.3"
        />
    <Button
        style="@style/Constraint_style"
        android:text="水平居中偏移70%"
        android:textAllCaps="false"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintHorizontal_bias="0.7"
        app:layout_constraintVertical_bias="0.7"
        />


</android.support.constraint.ConstraintLayout>

1.4可见性

约束布局的可见性属性:

  • 当控件设为GONE时,被认为尺寸为0,可以理解为布局上的一个点;
  • 当GONE的控件对其他控件有约束,则约束保留并生效,但所有的边距会清0.

1.5 尺寸

  • 设置固定尺寸
  • 使用wrap_content,根据内容计算合适大小
  • match_parent:填满父布局,此时设置的约束都不生效了。
  • 设置0dp,相当于MATCH_CONSTRAINT属性,基于约束最终确定大小。

MATH_CONSTRAINT

  • layout_constraintWidth_min和layout_constraintHeight_min:设置最小值
  • layout_constraintWidth_max和layout_constraintHeight_max:设置最大值
  • layout_constraintWidth_percent和layout_constraintHeight_percent:设置控件相对于父容器的百分比大小。使用之前需要先设置为百分比模式,然后设置宽高值为0-1之间。
    设置为百分比模式的属性:(ConstraintLayout在1.1.x以上才可以用)
app:layout_constraintWidth_default="percent" 
app:layout_constraintHeight_default="percent" 

下面是具体示例:


布局文件:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_dimen"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/btn_1"
        android:text="minWidth设置为200dp"
        android:textAllCaps="false"
        style="@style/Constraint_style"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:minWidth="200dp"
        />

    <Button
        android:id="@+id/btn_2"
        android:text="设置为MATCH_CONSTRAINT"
        style="@style/Constraint_style"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        app:layout_constraintTop_toBottomOf="@id/btn_1"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        />

    <Button
        android:id="@+id/btn_3"
        android:textAllCaps="false"
        android:text="layout_constrainedWidth开启"
        style="@style/Constraint_style"
        android:layout_marginTop="10dp"

        app:layout_constraintTop_toBottomOf="@id/btn_2"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constrainedWidth="true"
        app:layout_constraintWidth_min="300dp"
        />
    <Button
        android:id="@+id/btn_4"
        android:textAllCaps="false"
        android:text="layout_constrainedWidth关闭"
        style="@style/Constraint_style"
        android:layout_marginTop="10dp"

        app:layout_constraintTop_toBottomOf="@id/btn_3"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintWidth_min="300dp"
        />
    <Button
        android:id="@+id/btn_5"
        android:textAllCaps="false"
        android:text="宽50%高30%布局"
        style="@style/Constraint_style"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginTop="10dp"
        app:layout_constraintTop_toBottomOf="@id/btn_4"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintWidth_default="percent"
        app:layout_constraintHeight_default="percent"
        app:layout_constraintWidth_percent="0.5"
        app:layout_constraintHeight_percent="0.3"
        />
</android.support.constraint.ConstraintLayout>

1.6 比例

控件可以定义自身宽高之间的比例,前提条件是至少有一个尺寸设置为0dp,然后通过layout_constraintDimentionRatio属性设置宽高比。设置方式有以下几种:

  • 直接设置一个float值,表示宽高
  • 以“width:height”形式设置
  • 通过设置前缀W或H,指定一遍相对于另一边的尺寸,如“H,16:9”,高比宽为16:9

如果宽高设置为odp,也可以用ratio设置,这种情况下空间会满足比例约束的条件下,尽可能填满父布局。

下面是具体示例:


布局文件:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_dimen"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/btn_1"
        android:text="宽高比设置为2:1"
        style="@style/Constraint_style"
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        app:layout_constraintDimensionRatio="1:1"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        />

    <Button
        android:id="@+id/btn_2"
        android:text="宽高都设置为0dp,高宽比为16:9"
        style="@style/Constraint_style"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintDimensionRatio="H,16:9"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toBottomOf="@id/btn_1"
        android:textAllCaps="false"
        />

</android.support.constraint.ConstraintLayout>

1.7 链

链这个概念是约束布局新提出的,它提供了在一个维度(水平或者垂直),管理一组空间的方式。

2. Guideline

用于布局辅助,不在设备上显示。有垂直和水平两个方向(android:orientation=“vertical/horizontal”)

  • 垂直:宽度为0,高度等于父容器
  • 水平:高度为0,宽度等于父容器

有三种放置Guideline的方式:

  • 给定距离左边或顶部一个固定距离(layout_constraintGuide_begin)
  • 给定距离右边或底部一个固定距离(layout_constraintGuide_end)
  • 给定宽高一个百分比距离(layout_constraintGuide_percent)

具体示例:


布局文件:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_dimen"
    android:padding="16dp"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!--垂直Guideline-->
    <android.support.constraint.Guideline
        android:id="@+id/guideline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintGuide_percent="0.5"
        android:orientation="vertical"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        />
    <Button
        android:id="@+id/btn_1"
        android:textAllCaps="false"
        android:text="Guideline左边"
        style="@style/Constraint_style"
        app:layout_constraintRight_toLeftOf="@id/guideline"
        android:layout_marginTop="16dp"
        app:layout_constraintTop_toTopOf="parent"
        />


    <Button
        android:id="@+id/btn_2"
        android:textAllCaps="false"
        android:text="Guideline右边"
        style="@style/Constraint_style"
        app:layout_constraintLeft_toRightOf="@id/guideline"
        android:layout_marginTop="16dp"
        app:layout_constraintTop_toTopOf="parent"
        />

    <!--水平Guideline-->
    <android.support.constraint.Guideline
        android:id="@+id/h_guideline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintGuide_begin="200dp"
        />
    <Button
        android:id="@+id/btn_3"
        android:textAllCaps="false"
        android:text="Guideline上面"
        style="@style/Constraint_style"
        app:layout_constraintBottom_toBottomOf="@id/h_guideline"
        app:layout_constraintLeft_toLeftOf="parent"
        />
     <Button
        android:id="@+id/btn_4"
        android:text="Guideline下面"
        style="@style/Constraint_style"
        app:layout_constraintTop_toTopOf="@id/h_guideline"
        app:layout_constraintLeft_toLeftOf="parent"
        />

</android.support.constraint.ConstraintLayout>

3. ConstraintSet

通过ConstraintSet,允许在代码中进行约束设置,进行布局变换。(API 19及以上支持transmition动画)
创建ConstraintSet对象的几种方式:

  • 手动
c = new ConstraintSet(); 
c.connect(....);
  • 通过一个R.layout.xxx对象
c.clone(context, R.layout.layout1);
  • 通过一个ConstraintLayout对象
c.clone(clayout);

布局变化开启平滑动画的方式:

TransitionManager.beginDelayedTransition(constraintLayout);

其中参数constraintLayout表示动画作用的约束布局对象。
更多关于ConstraintSet的知识可以参考这篇文章

4.实践

效果图:



要求:图片宽高比16:9,图片宽度固定110dp。

分析:宽高比16:9,需要比例布局;其他都是一些位置关系,用约束布局相对位置的一些约束可以实现。

布局文件:

<?xml version="1.0" encoding="utf-8"?>
<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="wrap_content"
                                             android:paddingLeft="15dp"
                                             android:paddingTop="12dp">

    <ImageView
        android:id="@+id/iv_course"
        android:layout_width="110dp"
        android:layout_height="0dp"
        android:scaleType="fitXY"
        android:src="@mipmap/head"
        app:layout_constraintDimensionRatio="16:9"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/tv_course_name"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="15dp"
        android:ellipsize="end"
        android:maxLines="2"
        android:textColor="#333333"
        android:textSize="15sp"
        app:layout_constraintLeft_toRightOf="@id/iv_course"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="@id/iv_course"
        android:text="六年级单元过关检测六年级单元过关检测六年级单元过关检测" />


    <TextView
        android:id="@+id/tv_content"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginRight="15dp"
        android:layout_marginTop="5dp"
        android:ellipsize="end"
        android:maxLines="1"
        android:textColor="#666666"
        android:textSize="12sp"
        app:layout_constraintLeft_toLeftOf="@id/tv_course_name"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/tv_course_name"
        android:text="内容内容内容内容内容" />

    <TextView
        android:id="@+id/tv_current_price"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:maxLines="1"
        android:textColor="#f6454a"
        android:textSize="15sp"
        app:layout_constraintLeft_toLeftOf="@id/tv_course_name"
        app:layout_constraintTop_toBottomOf="@id/tv_content"
        android:text="¥ 480" />

    <TextView
        android:id="@+id/tv_origin_price"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="5dp"
        android:maxLines="1"
        android:textColor="#999999"
        android:textSize="12sp"
        app:layout_constraintBottom_toBottomOf="@id/tv_current_price"
        app:layout_constraintLeft_toRightOf="@id/tv_current_price"
        android:text="¥ 1480" />

</android.support.constraint.ConstraintLayout>

针对上面的效果
要求:图片宽度占整个布局30%,宽高比16:9。
分析:看到30%,首先考虑的是百分比布局,但是图片右边的view较多,每个都是设置一边百分比,实在是麻烦。因此,可以考虑使用Guideline,设置Guideline垂直,并距离父容器左边30%的距离,之后布局通过Guideline设置约束即可。
布局文件:

<?xml version="1.0" encoding="utf-8"?>
<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="wrap_content"
    android:paddingLeft="15dp"
    android:paddingTop="12dp">

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

    <ImageView
        android:id="@+id/iv_course"
        android:layout_width="110dp"
        android:layout_height="0dp"
        android:scaleType="fitXY"
        android:src="@mipmap/test"
        app:layout_constraintDimensionRatio="16:9"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="@id/guideline"
        app:layout_constraintTop_toTopOf="parent"
 />
...

要求:在之前基础上,底部加一根横线用于分隔,要求线与上面最近的控件距离是15dp。
分析:由于文字内容是可变的,当文字内容多的时候,线可能距离文字近;若文字不多,线也可能距离图片近。这个时候,基于当前最新1.0.2稳定版本的约束布局已经不能满足我们实现一层布局了,还是需要将图片和文字整体放入一个布局容器中,然后横线依赖这个布局容器设置约束实现,嵌套好像在所难免了。然而,当约束布局1.1.0稳定版本发布时,这问题也可以得到解决。我们先来看看在1.1.0上是怎么实现的:

<?xml version="1.0" encoding="utf-8"?>
<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="wrap_content"
    android:paddingLeft="15dp"
    android:paddingTop="12dp">

    <android.support.constraint.Guideline
        android:id="@+id/guideline"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        tools:layout_editor_absoluteY="0dp"
        tools:layout_editor_absoluteX="104dp"/>

    ...
    <android.support.constraint.Barrier
        android:id="@+id/barrier"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:barrierDirection="bottom"
        app:constraint_referenced_ids="iv_course, tv_origin_price"
        tools:layout_editor_absoluteY="79dp"
        tools:layout_editor_absoluteX="0dp"/>

    <View
        android:layout_width="329dp"
        android:layout_height="1dp"
        android:background="#d8d8d8"
        android:layout_marginTop="12dp"
        app:layout_constraintTop_toBottomOf="@+id/barrier"
        />
</android.support.constraint.ConstraintLayout>

具体关于Barrier的用法我们可以继续往下看。

5. ConstraintLayout的性能

  • 相对于传统布局,ConstraintLayout的布局层级减少了
  • 具体一些性能的对比,如渲染速度和计算次数等,可以参考这篇文章,< 了解使用 ConstraintLayout 的性能优势>,通过结论可知使用了ConstraintLayout,布局计算次数降低了,渲染速度也相应提升了。

6. 布局编辑器

Android studio 2.2之前的布局编辑器不够完善,部分约束不能设置,因此推荐使用版本为2.3或者更高的Android studio。关于布局编辑器可以参考下面这两边文章:

7. ConstraintLayout使用小结

7.1 margin只能设置正值或者0,负值无效

我们之前实现重叠布局时,或通过设置负的margin值实现,但是在约束布局中,负的margin值不会生效,只能设置0或者大于0 的值,小于0也当做0处理

7.2 链的书写方式注意

一般布局我们都是遵守先定义,后使用原则,但是约束布局实现链时,这个原则就遵守不了了,这个时候如果还是按照常规的@id/btn_2的方式指定一来控件(这个控件在当前控件之后声明),就会报Error:(23, 46) No resource found that matches the given name错误。解决方案其实很简单,只需修改指定方式如下:@+id/btn_2即可。

7.3 ConstraintSet动画Api支持等级

在代码中设置控件约束,可以通过ConstraintSet实现。约束变了之后,布局肯定会跟着变。TransitionManager.beginDelayedTransition提供了平滑动画变换布局的能力,但是只支持Api 19及以上的版本。

7.4 自定义GuideLine

对Guideline设置相对位置属性时不生效的,因此当我们想要一个相对于某个View的Guideline时,约束布局时不能满足我们的要求的,看Guideline源码:

public class Guideline extends View {
    public Guideline(Context context) {
        super(context);
        super.setVisibility(8);
    }
    ...    
}

发现Guideline是一个不可见的view,那么我们可以布局时放置一个不可见的view来作为Guideline的替代品,实现一些特殊布局要求。如布局重叠:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"

    >
    <Button
        android:id="@+id/btn_a"
        android:layout_width="0dp"
        android:layout_height="200dp"
        android:text="B"
        android:textSize="20sp"
        android:textColor="@color/white"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:background="#fd368d"
        tools:layout_editor_absoluteY="0dp"/>
    <View
        android:id="@+id/view"
        android:layout_height="0dp"
        android:layout_width="0dp"
        app:layout_constraintBottom_toBottomOf="@id/btn_a"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:layout_marginBottom="40dp"/>
    <Button
        android:text="A"
        android:layout_height="200dp"
        android:layout_width="wrap_content"
        android:textColor="@color/white"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:background="@color/colorPrimary"
        app:layout_constraintTop_toBottomOf="@id/view"/>

</android.support.constraint.ConstraintLayout>

效果图:



这种方式可以弥补margin不能设置为负值的不足

7.5 区分0dp、match_parent和MATCH_CONSTRAINT

  • 0dp等价于MATCH_CONSTRAINT,对控件设置其他尺寸相关约束会生效,如app:layout_constraintWidth_min等约束
  • match_parent,填充满父布局,之后设置约束属性无效

7.6 使用布局编辑器多出了一些属性

layout_optimizationLevel
layout_editor_absoluteX
layout_editor_absoluteY
layout_constraintBaseline_creator
layout_constraintTop_creator
layout_constraintRight_creator
layout_constraintLeft_creator
layout_constraintBottom_creator

这几个属性是 UI 编辑器所使用的,用了辅助拖拽布局的,在实际使用过程中,可以不用关心这些属性。

8. 1.1.0-beta3的新特性

  • Barrier
    Barrier是一个虚拟的辅助控件,它可以阻止一个或者多个控件越过自己,就像一个屏障一样,当某个控件要越过自己的时候,Barrier会自动移动,避免自己被覆盖。
  • Group
    Goup帮助你对一组控件进行设置,最常见的情况就是控制一组控件的visibility,你只需把控件的id添加到group,就能同时对立面的所有控件进行操作。
  • Circular positioning
    可以相对另一个控件,以角度和距离定义当前控件的位置,即提供了在圆上定义控件位置的能力,如图所示:


  • Placeholder
    Placeholder顾名思义,就是用来一个占位的东西,它可以把自己的内容设置为ConstraintLayout内的其他view,因此它用来写布局的模板,也可以用来动态修改UI的内容。
  • 百分比布局
    允许设置控件占据可用空间的百分比,大大增加布局灵活度和适配性。

具体文章参考Constraint Layout 1.1.x带来了哪些新东西?

9. ConstraintLayout的优势

  • 布局高效
  • 轻松对应复杂布局
  • 嵌套层级少
  • 适配性好
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,463评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,868评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,213评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,666评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,759评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,725评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,716评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,484评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,928评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,233评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,393评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,073评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,718评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,308评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,538评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,338评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,260评论 2 352

推荐阅读更多精彩内容