相关文章推荐
大气的海龟  ·  整理PHPMailer 发送邮件 ...·  1 年前    · 
想出国的苦瓜  ·  python ...·  1 年前    · 
坚强的松球  ·  sql server - ...·  2 年前    · 

国际惯例,官网参考文档是最好的学习资料:

使用 ConstraintLayout 构建自适应界面

约束布局 ConstraintLayout ,也有人把它称作“增强型的相对布局”,扁平式的布局方式,无任何嵌套,减少布局的层级,优化渲染性能。是最受欢迎的 Jetpack 库之一,其实是 Android Studio 2.2 中主要的新增功能之一,也是 Google 在2016年的 I/O 大会上重点宣传的一个功能。AS 已经将它作为新建页面默认布局了。经历这几年的迭代,功能已经非常的成熟,现在 2.0 正式版本也发布了,也许你已熟悉了旧版本中的功能,并开始用它来快速构建复杂的页面布局,而新版本除了包含旧版本中的所有功能之外,还在 AS 中集成了可以直接预览 XML 的工具,甚至可以直接在预览界面中对布局进行编辑。

二,控件优点

ConstraintLayout 可以理解为 RelativeLayout + LinearLayout 的混合强化版,同时新版 Android Studio 的布局编辑器也提供了对 ConstraintLayout 完善的编辑支持。使用 ConstraintLayout 可以很方便地在一个层级上实现复杂的布局,功能也很完善,是 Android 官方目前非常重视的一个 Layout(替代以前的 RelativeLayout),使用 ConstraintLayout 后基本可以抛弃 LinearLayout 和 RelativeLayout 的使用,完全不需要任何嵌套就可以实现复杂的 UI,使用起来特别清爽。减少了很多的嵌套的层级,这样 View 在渲染的时候,减少了很多多余的 measure layout 的开销,如果嵌套的层次越多,提升的效果越明显。

感兴趣的话看官方给出的性能测试示例: 解析ConstraintLayout的性能优势

三,项目中引入

如需在项目中使用 ConstraintLayout ,请按以下步骤操作:

  1. 确保你的 maven.google.com 代码库已在模块级 build.gradle 文件中声明:
repositories {
    google()
  1. 将该库作为依赖项添加到同一个build.gradle文件中,如以下示例所示。请注意,最新版本可能与示例中显示的不同:
dependencies {
       implementation "androidx.constraintlayout:constraintlayout:2.0.4"
       // To use constraintlayout in compose
       implementation "androidx.constraintlayout:constraintlayout-compose:1.0.0-alpha05"
  1. 在工具栏或同步通知中,点击 Sync Project with Gradle Files

现在,你可以使用 ConstraintLayout 构建布局。

四,基本使用

4.1 相对位置

要在ConstraintLayout 中确定 view 的位置,必须至少添加一个水平和垂直的约束。每一个约束表示到另一个 view、父布局或者不可见的参考线的连接或者对齐。如果水平或者垂直方向上没有约束,那么其位置就是0。

下面是 ConstraintLayout 确定位置的属性,这些属性的值即可以是 parent(父布局),也可以是某个 view 的 id,和同类型的RelativeLayout属性很相似:

ConstraintLayoutRelativeLayout作用
layout_constraintLeft_toLeftOflayout_alignLeft与参照控件左对齐
layout_constraintLeft_toRightOflayout_toRightOf在参照控件的右边
layout_constraintRight_toLeftOflayout_toLeftOf在参照控件的左边
layout_constraintRight_toRightOflayout_alignRight与参照控件右对齐
layout_constraintTop_toTopOflayout_alignTop与参照控件上对齐
layout_constraintTop_toBottomOflayout_below在参照控件底部
layout_constraintBottom_toTopOflayout_alignBottom在参照控件的上部
layout_constraintBottom_toBottomOflayout_above与参照控件下对齐
layout_constraintBaseline_toBaselineOflayout_alignBaseline与参照控件基线对齐
layout_constraintStart_toEndOf
layout_constraintStart_toStartOf
layout_constraintEnd_toStartOf
layout_constraintEnd_toEndOf

说明:这里 start/end 一般情况下和 left/right 是一样的效果,主要是为了做国际化适配,方便从右往左读的语言文字(如阿拉伯文)。

一个简单的页面:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="左对齐"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="右对齐"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="水平居中"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="垂直居中"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="底部对齐"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="水平居中+垂直居中"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

在这里插入图片描述
居中显示:

即view的左边对齐父布局的左边,view的右边对齐父布局的右边,除非这个view的大小刚好充满整个父布局; 否则的话,就是水平居中显示了。我们可以理解为有两个相同的力,把view拉到中间。 app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent"

水平方向的相对位置:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app=




    
"http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button
        android:id="@+id/btn_center"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="水平参照物"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Left_toLeftOf"
        app:layout_constraintBottom_toTopOf="@id/btn_center"
        app:layout_constraintLeft_toLeftOf="@id/btn_center"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Right_toLeftOf"
        app:layout_constraintBottom_toTopOf="@id/btn_center"
        app:layout_constraintRight_toLeftOf="@id/btn_center"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Right_toRightOf"
        app:layout_constraintRight_toRightOf="@id/btn_center"
        app:layout_constraintTop_toBottomOf="@id/btn_center"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Left_toRightOf"
        app:layout_constraintLeft_toRightOf="@id/btn_center"
        app:layout_constraintTop_toBottomOf="@id/btn_center"/>
</androidx.constraintlayout.widget.ConstraintLayout>

效果如下:
在这里插入图片描述
竖直方向的相对位置:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button
        android:id="@+id/btn_center"
        android:layout_width="wrap_content"
        android:layout_height="100dp"
        android:text="竖直参照物"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Top_toTopOf"
        app:layout_constraintTop_toTopOf="@id/btn_center"
        app:layout_constraintRight_toLeftOf="@id/btn_center"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Bottom_toTopOf"
        app:layout_constraintBottom_toTopOf="@id/btn_center"
        app:layout_constraintRight_toLeftOf="@id/btn_center"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Top_toBottomOf"
        app:layout_constraintLeft_toRightOf="@id/btn_center"
        app:layout_constraintTop_toBottomOf="@id/btn_center"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text=




    
"Bottom_toBottomOf"
        app:layout_constraintLeft_toRightOf="@id/btn_center"
        app:layout_constraintBottom_toBottomOf="@id/btn_center"/>
</androidx.constraintlayout.widget.ConstraintLayout>

4.2 尺寸约束

view 中使用 warp_content 或者固定值等等是没有问题的。但是在 ConstraintLayout 中不推荐使用 match_parent 这个值,如果需要实现跟 match_parent 同样的效果,可以使用 0dp 来代替,其表示 match_parent,即适应约束。其跟 match_parent 还是有区别的,后面的例子(宽高比那一小节)会提到。
我们来看下例子:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button
        android:id="@+id/btn_center"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>
    <Button
        android:id="@+id/btn_1"
        android:layout_width="180dp"
        android:layout_height="wrap_content"
        android:text="具体数值:180dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/btn_center"/>
    <Button
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="0dp(match_parent)"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/btn_1"/>
</androidx.constraintlayout.widget.ConstraintLayout>

4.3 宽高比 Ratio

ConstraintLayout 中,还可以将宽定义成高的一个比例或者高定义成宽的比率。首先,需要将宽或者高设置为0dp(即match_parent),即要适应约束条件。然后通过 layout_constraintDimensionRatio 属性设置一个比率即可。这个比率可以是一个浮点数,表示宽度和高度之间的比率;也可以是“宽度:高度”形式的比率。比如:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        android:layout_marginTop="30dp"
        app:layout_constraintTop_toTopOf="parent"
        android:text="-------------------宽高比2:1-------------------"
        app:layout_constraintDimensionRatio="2:1"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

在这里插入图片描述
如果宽和高都设置为0dp(match_parent),那么 layout_constraintDimensionRatio 的值需要先加一个"W,"或者"H,"来表示约束宽度或高度。如下:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintDimensionRatio="H,16:9"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

4.4 百分比宽高 Percent

ConstraintLayout 还能使用百分比来设置 view 的宽高。要使用百分比,宽或高同样要设置为 0dp(match_parent)。然后设置以下属性即可:

app:layout_constraintWidth_default="percent" //设置宽为百分比,可以设置percent、spread和wrap
app:layout_constraintWidth_percent="0.3" //0到1之间的值,为占父布局宽度的多少
app:layout_constraintHeight_default="percent" //设置高为百分比,可以设置percent、spread和wrap
app:layout_constraintHeight_percent="0.3" //0到1之间的值,为占父布局宽度的多少

例子如下:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:




    
layout_width="match_parent"
    android:layout_height="match_parent">
    <Button
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="宽50%"
        app:layout_constraintWidth_default="percent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintWidth_percent="0.5"/>
</androidx.constraintlayout.widget.ConstraintLayout>

注:在早期版本中必需手动指定 app:layout_constraintWidth_default=“percent”,在之后的版本中如果设置了app:layout_constraintWidth_percent 属性,则可以不用指定。

效果如下:
在这里插入图片描述
官网的介绍是这样的:

You can also define one dimension of a widget as a ratio of the other one. In order to do that, you need to have at least one constrained dimension be set to 0dp (i.e., MATCH_CONSTRAINT), and set the attribute layout_constraintDimensionRatio to a given ratio

意思是说约束布局支持子控件设置宽高比,前提条件是至少需要将宽高中的一个设置为0dp。为了约束一个特定的边,基于另一个边的尺寸,可以预先附加W,或H以逗号隔开。

4.5 偏移量 bias

如果想让view的位置偏向某一侧,可以使用以下的两个属性来设置:

layout_constraintHorizontal_bias  //水平偏向
layout_constraintVertical_bias  //竖直偏向

其值同样也是0到1之间。比如,以下例子为横向偏向左侧30%,默认的居中效果就是50%:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="左边偏向30%"
        app:layout_constraintHorizontal_bias="0.3"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

显示效果如下:
在这里插入图片描述

4.6 圆形定位 Circular positioning

以一个控件为圆心设置角度和半径定位

  • layout_constraintCircle:关联另一个控件,将另一个控件放置在自己圆的半径上,会和下面两个属性一起使用
  • layout_constraintCircleRadius:圆的半径
  • layout_constraintCircleAngle:圆的角度

4.7 权重 weight

LinearLayout中可以设置权重,ConstraintLayout 同样也有这个属性。通过设置以下两个属性:

app:layout_constraintHorizontal_weight //水平权重
app:layout_constraintVertical_weight //竖直权重

然后将相连的 view 两两约束好即可。如下:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button
        android:id="@+id/btn_1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="权重为1"
        app:layout_constraintHorizontal_weight="1"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@id/btn_2"/>
    <Button
        android:id="@+id/btn_2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="权重为2"
        app:layout_constraintHorizontal_weight="2"
        app:layout_constraintLeft_toRightOf="@id/btn_1"
        app:layout_constraintRight_toLeftOf="@id/btn_3"/>
    <Button
        android:id="@+id/btn_3"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintHorizontal_weight="2"
        android:text="权重为2"
        app:layout_constraintLeft_toRightOf="@id/btn_2"
        app:layout_constraintRight_toRightOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

4.8 辅助线 Guideline

Guideline 可以用来辅助布局,通过 Guideline 能创建出一条水平线或者垂直线,该线不会显示到界面上,但是能够利用这些线条来添加约束去完成界面的布局。

Guideline主要的属性有:

android:orientation="horizontal|vertical" 
app:layout_constraintGuide_begin="30dp" 
app:layout_constraintGuide_end="30dp"
app:layout_constraintGuide_percent="0.5"
android:orientation=”horizontal|vertical”表示是水平或垂直引导线。
app:layout_constraintGuide_begin=”30dp”,如果是水平引导线,则距离布局顶部30dp,如果是垂直引导线,则距离布局左边30dp。
app:layout_constraintGuide_end=”30dp”,如果是水平引导线,则距离布局底部30dp,如果是垂直引导线,则距离布局右边30dp。
app:layout_constraintGuide_percent=”0.5”,如果是水平引导线,则距离布局顶部为整个布局高度的50%,如果是垂直引导线,则距离布局左边文这个布局宽度的50%。

来看个例子:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <androidx.constraintlayout.widget.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"/>
    <androidx.constraintlayout.widget.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"/>
    <Button
        app:layout_constraintLeft_toLeftOf="@id/guideline_v"
        app:layout_constraintTop_toTopOf="@id/guideline_h"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="辅助线定位"/>
</androidx.constraintlayout.widget.ConstraintLayout>

如下图所示:
在这里插入图片描述

4.9 屏障 Barrier

Barrier,直译为障碍、屏障。在约束布局中,可以使用属性constraint_referenced_ids属性来引用多个带约束的组件,从而将它们看作一个整体,Barrier 的介入可以完成很多其他布局不能完成的功能。

开发中有这样的一个需求,看下图:
在这里插入图片描述
姓名、联系方式位于左侧区域(随着文本的宽度变化左侧区域的宽度也随之变化),使用传统的布局方式实现嵌套过多,布局不够优雅。那么来看看约束布局是怎么去实现的:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="20dp">
    <TextView
        android:id="@+id/tv_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="姓名:"
        app:layout_constraintBottom_toBottomOf="@+id/et_name"
        app:layout_constraintTop_toTopOf="@+id/et_name"/>
    <TextView
        android:id="@+id/tv_contract"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:text="联系方式:"
        app:layout_constraintBottom_toBottomOf="@+id/et_contract"
        app:layout_constraintTop_toTopOf="@+id/et_contract"/>
    <EditText
        android:id="@+id/et_name"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:hint="请输入姓名"
        app:layout_constraintLeft_toLeftOf="@+id/barrier"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>
    <EditText
        android:id="@+id/et_contract"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:hint="请输入联系方式"
        app:layout_constraintLeft_toLeftOf="@+id/barrier"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/et_name"/>
    <androidx.constraintlayout.widget.Barrier
        android:id="@+id/barrier"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:barrierDirection="right"
        app:constraint_referenced_ids="tv_name,tv_contract"/>
</androidx.constraintlayout.widget.ConstraintLayout>

barrierDirection 指定方向,constraint_referenced_ids引用的控件 id(多个id以逗号隔开)。

4.10 Group

Group用于控制多个控件的可见性。使用非常简单,若 android:visibility="gone" 那么 btn1,btn2 控件都会隐藏。

<androidx.constraintlayout.widget.Group
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:visibility="visible"
    app:constraint_referenced_ids="btn1,btn2">
    <Button
        android:id="@+id/btn1"
        android:text="btn1"
        android:layout_width=




    
"wrap_content"
        android:layout_height="wrap_content"/>
    <Button
        android:id="@+id/btn2"
        android:text="btn2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</androidx.constraintlayout.widget.Group>

4.11 隐藏边距 goneMargin

当约束目标的可见性为View.GONE时,还可以通过以下属性设置不同的边距值:

layout_goneMarginStart
layout_goneMarginEnd
layout_goneMarginLeft
layout_goneMarginTop
layout_goneMarginRight
layout_goneMarginBottom

4.12 链 Chains

上面这种将相连的 view 两两约束好的实际上就形成了链。在 ConstraintLayout 中可以实现各种不同的链,权重链是其中一种。整个链由链中的第一个view(链头)上设置的属性控制。

官网上一共有4种样式的链:
在这里插入图片描述

  • Spread:视图是均匀分布的(在考虑外边距之后)。这是默认值。
  • Spread inside:第一个和最后一个视图固定在链两端的约束边界上,其余视图均匀分布。
  • Weighted:当链设置为 spread 或 spread inside 时,您可以通过将一个或多个视图设置为“match_parent”(0dp) 来填充剩余空间。默认情况下,设置为“match_parent”的每个视图之间的空间均匀分布,但您可以使用 layout_constraintHorizontal_weight 和 layout_constraintVertical_weight 属性为每个视图分配重要性权重。如果您熟悉线性布局中的 layout_weight 的话,就会知道该样式与它的原理是相同的。因此,权重值最高的视图获得的空间最大;相同权重的视图获得同样大小的空间。
  • Packed:视图打包在一起(在考虑外边距之后)。 然后,您可以通过更改链的头视图偏差调整整条链的偏差(左/右或上/下)。
layout_constraintHorizontal_chainStyle // 横向约束链
layout_constraintVertical_chainStyle // 纵向约束链

五,ConstraintLayout 2.0 新特性

官方更新文档:What’s New in 2.1

5.1 新增VirtualLayouts:Flow布局

Flow布局是Chains的强化版,是一种新的VirtualLayouts。用于构建流式排版效果:当出现空间不足时,可自动换行或自动延展到屏幕的另一区域。即当需要对多个View进行流式布局 / 不确定其布局空间的实际尺寸时,就可使用Flow布局。
在这里插入图片描述
使用步骤:

  1. 通过属性constraint_referenced_ids获取要引用的视图;
  2. 根据这些视图创建一个虚拟的virtual view group;
  3. 对这些视图进行流式布局。
<androidx.constraintlayout.helper.widget.Flow
 	app:constraint_referenced_ids="a1,a2,a3"
    app:flow_wrapMode="aligned"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent" />

核心属性:flow_wrapMode,用于控制元素的排列方式。
wrapMode
属性说明如下:

<androidx.constraintlayout.helper.widget.Flow
 	app:constraint_referenced_ids="a1,a2,a3"
    app:flow_wrapMode="aligned"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent" />
NONE : 默认模式。Views不会被包裹到另一行或列。如果它们在屏幕之外,则不能被看到。
CHAIN : CHAIN与Chains非常相似,可以认为是Chains的强化版本。CHAIN是根据orientation逐行或逐列进行排列的,默认的展示风格是SPREAD。
ALIGNED : ALIGNED模式与CHAIN类似,但链式是在将不同行和列的视图对齐后考虑的,默认的样式是SPREAD。

5.2 可自定义ConstraintHelper

ConstraintHelper 是一个用于记录标记 Views 的 Helper,通过引用指定 Views 从而实现具体效果。

  • 辅助布局:创建一个新的布局方式,避免创建新的 ViewGroup 从而加深层级
  • 修改布局:在布局完成后,修改布局效果
  • 重新渲染:在View绘制完成后,对View进行修改、重新渲染效果

具体使用:通过继承 ConstraintHelper 类实现 & 重写所需回调,具体如下所示。

// 继承ConstraintHelper类
class carsonhoTest @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : ConstraintHelper(context, attrs, defStyleAttr) {
 // 复写常用方法
    override fun updatePostLayout(container: ConstraintLayout?) {
        super.updatePostLayout(container)
        getViews(container).forEach { view ->
            ViewAnimationUtils.createCircularReveal(
                view, view.width / 3,
                view.height / 3, 0f,
                hypot((view.height / 3.0), (view.width / 3.0)).toFloat()
            ).apply {
                duration = 2000
                start()
// 常用方法说明
init() // 初始化调用
updatePreLayout() // 布局前更新
updatePostLayout() // 布局后更新
updatePostMeasure() // 测量后更新
updatePostConstraints() // 更新约束
onDraw() // 进行绘制

5.3 新增切换状态布局功能:ConstraintLayoutStates

ConstraintLayoutStates 用于根据状态切换不同的布局文件。

// 步骤1:创建不同状态的layout xml文件,布局文件的root id相同即可。
// 如:states_1、states_2
// 步骤2:在xml文件夹下创建管理文件
<?xml version="1.0" encoding="utf-8"?>
<ConstraintLayoutStates xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <State
        android:id="@+id/state1"
        app:constraints="@layout/states_1" />
    <State
        android:id="@+id/state2"
        app:constraints="@layout/states_2" />
</ConstraintLayoutStates>
// 步骤3:使用loadLayoutDescription来加载管理文件
val constraintLayout = findViewById<ConstraintLayout>(R.id.constraint_state)
constraintLayout.loadLayoutDescription(R.xml.constraint_layout_states)
constraintLayout.setOnClickListener {
    // 点击时切换布局文件
    constraintLayout.setState(R.id.state2, 0, 0)

5.4 新增创建约束工具类:ConstraintProperties

ConstraintProperties 是在代码中创建约束的工具类。
具体使用:在该工具类出来前,修改属性的常用方式是:

ConstraintSet().apply {
    clone(constraintLayout)
    setTranslationX(R.id.xxx, 32f)
    setMargin(R.id.xxx, ConstraintSet.START, 42)
    applyTo(constraintLayout)

对于 ConstraintLayoutStates,可使用流式 API 修改属性,更加方便快捷。

ConstraintProperties(findViewById(R.id.xxx))
    .translationZ(8f)
    .margin(ConstraintSet.START, 8)
    .apply()

PS. 推荐阅读

国际惯例,官网参考文档是最好的学习资料:使用 ConstraintLayout 构建自适应界面1,背景约束布局 ConstraintLayout 是最受欢迎的 Jetpack 库之一,其实是Android Studio 2.2中主要的新增功能之一,也是 Google 在2016年的 I/O 大会上重点宣传的一个功能。AS 已经将它作为新建页面默认布局了。经历这几年的迭代,功能已经非常的成熟,现在 2.0 正式版本也发布了,也许你已熟悉了旧版本中的功能,并开始用它来快速构建复杂的页面布局,而新版本除了包 2.2 ConstraintLayout 怎么用 2.2.1 了解一些该知道的 1.ConstraintLayout是一个ViewGroup,可以在Api 9以上的Android系统使用。 2.英语牛*的去官网了解一下吧>>>>>>ConstraintLayout官网介绍 3.关于View的上下左右 2.2.2 属性之我的哪里想挨着你的哪里(相对定位) layout ( 1 ) ConstraintLayout 依赖添加 ( 2 ) ConstraintLayout 转换 与 添加 二. ConstraintLayout 约束 的 基本操作 1. 约束基本操作 ( 1 ) Design ( 设计 ) 和 Bluepr
一、什么是约束布局ConstraintLayoutConstraintLayout 是一个使用“相对定位”灵活地确定微件的位置和大小的一个布局,在 2016 年 Google I/O 中面世,它的出现是为了解决开发中过于复杂的页面层级嵌套过多的问题——层级过深会增加绘制界面需要的时间,影响用户体验,以灵活的方式定位和调整小部件。 ConstraintLayout 是一个ViewGroup,可以在Api9以上的Android系统使用它,它的出现主要是为了解决布局嵌套过多的问题,以灵活的方式定位和调整小
前言ConstraintLayout是一个使用“相对定位”灵活地确定微件的位置和大小的一个布局,在 2016 年 Google I/O 中面世,它的出现是为了解决开发中过于复杂的页面层级嵌套过多的问题——层级过深会增加绘制界面需要的时间,影响用户体验,以灵活的方式定位和调整小部件。 从 Android Studio 2.3起,创建layout文件就已经是默认ConstraintLayout了,但是尽管Google如此大力推这项技术,但在当时很少有人使用,近些年逐渐被大家拿起来,啊真香!(此处无图胜有...