约束布局所具有的优势:

1.较高的性能优势。

布局嵌套层次越高,性能开销越大。而使用ConstraintLayout,经常就一层嵌套就搞定了,所以其性能要好很多。

2.完美的屏幕适配.
ConstraintLayout的大小、距离都可以使用比例来设置,所以其适配性更好。

3.书写简单

4.可视化编辑。
ConstraintLayout也有十分方便完善的可视化编辑器,不用写xml也基本上能实现大部分功能

定位位置

确定位置的属性提供了下面13个属性(就是哪一条边和哪一条边对齐)

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

例如layout_constraintLeft_toRightOf constraintLeft指的当前控件的左边,toRightOf 对应其他控件的右边

View的边界界定图

实现控件居中和偏移量bias

实现居中直接使用如下代码即可

1
2
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"

实现控件处于水平方向的1/3的位置。使用偏移量bias属性。bias即偏移量,他们的取值范围从0~1,0即挨着左边,1是挨着右边,所以要使处于1/3处

1
2
3
app:layout_constraintHorizontal_bias="0.33"
垂直方向
app:layout_constraintVertical_bias="0.33"

view控件大小设置

layout_constraintWidth_default属性有三种不同的值:

spread默认值,意思是占用所有的符合约束的空间 。直接设置 layout_width = “0dp”

就直接占满整个空间

percent,意思是按照父布局的百分比设置,需要layout_constraintWidth_percent设置百分比例

1
2
3
4
5
6
7
8
<Button
android:id="@+id/d"
android:layout_width="0dp"
android:layout_height="50dp"
app:layout_constraintWidth_percent="0.3"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/c" />

设置了layout_constraintWidth_percent属性,可以不用指定layout_constraintWidth_default,他会自动设置为percent
wrap,意思匹配内容大小但不超过约束限制,注意和直接指定宽度为wrap_content的区别就是不超过约束限制

第一行宽度达到约束就不再增加,第二行显示了完整内容

宽高比ratio

layout_constraintDimensionRatio即宽和高成一定的比例,其值可以是”width:height”的形式,也可以是width/height的值。该属性生效的前提:宽和高其中有一项为0dp,有constraint。

如果两项都为0dp,则尺寸会设置为满足约束的最大值并保持比例。

在一个水平或者竖直方向上,一排view两两互相约束,即为链

链式布局是约束布局常用的另一个强大功能,可以快速实现等分布局等,还可以实现类似LinearLayout布局的weight比重功能。

约束链具有三种模式:

  • spread:view之间均匀分布
  • spread_inside:除了约束链的头部和尾部贴在两边,其余均匀分布
  • packed:所有view紧贴在一起,默认居中
    图片

将多个view构建成一个水平方向的链,则需要多个view在水平方向上两两约束

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<Button
android:id="@+id/k"
android:layout_width="0dp"
android:layout_height="50dp"
android:text="k"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintTop_toBottomOf="@id/j"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/m"/>
<Button
android:id="@+id/m"
android:layout_width="0dp"
android:layout_height="50dp"
android:text="m"
android:layout_marginHorizontal="10dp"
app:layout_constraintLeft_toRightOf="@+id/k"
app:layout_constraintRight_toLeftOf="@+id/l"
app:layout_constraintTop_toBottomOf="@id/j" />

<Button
android:id="@+id/l"
android:layout_width="0dp"
android:layout_height="50dp"
android:text="l"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toRightOf="@id/m"
app:layout_constraintTop_toBottomOf="@id/j" />

链的第一个view,称为链头。在链头上设置app:layout_constraintHorizontal_chainStyleapp:layout_constraintVertical_chainStyle可分别设置水平或垂直链的模式。
使用layout_constraintHorizontal_weight,来分割剩余空间。

android:layout_weight区别

  • layout_weight ,不管当前view的大小设的是多大,都会继续占据剩余空间
  • layout_constraintHorizontal_weight,这个只对0dp并且layout_constraintWidth_default为spread的view生效,使其大小按比例分割剩余空间,对于已经设定大小的view不生效
    图片

圆形布局

约束布局还提供一种炫酷的圆形布局:可以以角度和距离约束某个view中心相对于另一个view的中心。

  • app:layout_constraintCircle : 圆心,值是某个view的id
  • app:layout_constraintCircleRadius : 半径
  • app:layout_constraintCircleAngle :角度,值是从0-360,0是指整上方
    图片
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<Button
android:id="@+id/m"
android:layout_width="100dp"
android:layout_height="50dp"
android:text="m"
app:layout_constraintLeft_toRightOf="@+id/k"
app:layout_constraintRight_toLeftOf="@+id/l"
app:layout_constraintTop_toBottomOf="@id/j" />

<!--圆形布局-->
<Button
android:id="@+id/n"
android:layout_width="100dp"
android:layout_height="50dp"
android:text="圆形布局"
app:layout_constraintCircle="@id/m"
app:layout_constraintCircleAngle="220"
app:layout_constraintCircleRadius="100dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/m"/>

辅助组件

约束布局还提供了一系列组件使得可以更灵活地布局。如Group可以同时控制一堆view的可见性,GuideLine可以虚拟一条辅助线等等。

Group:控制可见性

Group是一个虚拟视图,可以通过把viewapp:constraint_referenced_ids放到里面,统一同时控制这些view的可见性。

1
2
3
4
5
<androidx.constraintlayout.widget.Group
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/group"
app:constraint_referenced_ids="a,b"/>

Group也是继承自view的,直接在代码中像普通view一样设置可见性,就能同时控制到img1,img2的可见性了。

Guideline:辅助线

Guideline相当于一条虚拟辅助线,可分为水平、垂直线,帮助定位的。

考虑一个需求,两个view,要在屏幕中间一左一右,若是传统定位,就弄一个线性布局放两个view,然后再把这个线性布局居中。使用约束布局,可以在屏幕正中间放一条虚拟垂直辅助线,然后两个view分别放在这条线左右即可。

图片

android:orientation设置垂直还是水平

app:layout_constraintGuide_percent通过百分比设置位置,取值可以是0f-1.0f或0%-100%

app:layout_constraintGuide_begin设置相对start/top的偏移量,dp

app:layout_constraintGuide_end设置相对end/bottom的偏移量,dp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
 <androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.5" />



<Button
android:id="@+id/o"
android:layout_width="100dp"
android:layout_height="50dp"
android:text="o"
android:layout_marginRight="10dp"
app:layout_constraintRight_toLeftOf="@+id/guideline"
app:layout_constraintTop_toBottomOf="@id/n" />



<Button
android:id="@+id/p"
android:layout_width="100dp"
android:layout_height="50dp"
android:text="p"
android:layout_marginLeft="10dp"
app:layout_constraintLeft_toRightOf="@id/guideline"
app:layout_constraintTop_toBottomOf="@id/n" />

Barrier:获取边界范围

Barrier可以获取多个约束view的边界。可以获得所包含的多个view的最左最右等边界

考虑这样一个需求,左边是text1和text2,另外有一个view,必须放在这两个text的右边

图片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<TextView
android:id="@+id/r"
android:layout_width="100dp"
android:layout_height="50dp"
android:layout_marginLeft="10dp"
android:background="@color/black"
android:gravity="center"
android:text="R"
android:textColor="@color/white"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<TextView
android:id="@+id/s"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
android:background="@color/purple_200"
android:gravity="center"
android:text="ssadadasdasds"
android:textColor="@color/white"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/r" />

<Button
android:id="@+id/t"
android:layout_width="100dp"
android:layout_height="50dp"
android:layout_marginLeft="10dp"
android:text="t"
app:layout_constraintBottom_toBottomOf="@+id/s"
app:layout_constraintLeft_toRightOf="@+id/r"
app:layout_constraintTop_toTopOf="@+id/r" />

因为t只能有一个描点,所以以text1为约束点。但text1、text2宽度时动态的,当text2文本过长时,会发生遮挡。
图片

此时barrier就派上用场了,它可以动态获取text1、text2的最右侧,这样只要t依赖改为Barrier的最右侧,就可以解决问题了

图片

app:barrierDirection,取值有top、bottom、left、right、start、end,用于设置获取的是哪侧,比如上面的例子,获取的是最右侧start/right。

app:constraint_referenced_ids设置需要包含的view的id

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<androidx.constraintlayout.widget.Barrier
android:id="@+id/barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="end"
app:constraint_referenced_ids="r,s" />

<TextView
android:id="@+id/r"
android:layout_width="100dp"
android:layout_height="50dp"
android:layout_marginLeft="10dp"
android:background="@color/black"
android:gravity="center"
android:text="R"
android:textColor="@color/white"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<TextView
android:id="@+id/s"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
android:background="@color/purple_200"
android:gravity="center"
android:text="ssadadasdasdsasdasda"
android:textColor="@color/white"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/r" />

<Button
android:id="@+id/t"
android:layout_width="100dp"
android:layout_height="50dp"
android:layout_marginLeft="10dp"
android:text="t"
app:layout_constraintBottom_toBottomOf="@+id/s"
app:layout_constraintLeft_toRightOf="@+id/barrier"
app:layout_constraintTop_toTopOf="@+id/r" />