ConstraintLayout核心用法详解(二):尺寸约束与链约束
整理旧电脑上的一些笔记。
往期文章
今天继续整理 ConstraintLayout。
ConstraintLayout 的特点:
-
扁平布局,无嵌套,一个层级就可以绘制复杂布局;
-
渲染性能高;
-
集合了线性布局、相对布局、百分比布局的特点和大多数功能;
-
支持可视化环境下拖拽绘制约束布局;
-
轻松地为应用中使用的 UI 组件添加动画效果。
1. 尺寸约束
尺寸约束包括设置 View最大/最小值、设置百分比、设置宽高比例,下面分别介绍。
1.1 最大最小值
控件宽或高为WRAP_CONTENT时候,设置控件最大值或最小值可以使用下面属性:
- android:minWidth="",设置布局最小宽度
- android:minHeight="",设置布局最小高度
- android:maxWidth="",设置布局最大宽度
- android:maxHeight="",设置布局最大高度
控件宽或高为 0dp,即 MATCH_CONSTRAINTS(不可以设置为match_parent),控件占用剩余可用的全部空间。代码和示意图如下:
<TextView
android:id="@+id/tv_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#7CB342"
android:maxWidth="300dp"
android:minWidth="20dp"
android:text="Hello ConstraintLayout"
android:textSize="22sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@color/purple_200"
android:gravity="center"
android:text="Hello ConstraintLayout!"
android:textColor="@color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />

1.2 百分比布局
早期 Android 中有专门的百分比布局方式——PercentFrameLayout和PercentRelativeLayout,但早已被废弃。ConstraintLayout 支持百分比布局,现代的百分比布局方式更加推荐使用ConstraintLayout。实现步骤如下:
- layout_width或layout_height设置为0dp(MATCH_CONSTRAINT);
- 设置layout_constraintWidth_default="percent"或layout_constraintHeight_default="percent";
- 使用layout_constraintWidth_percent或layout_constraintHeight_percent属性设置百分比,值为0-1之间。
XML中代码如下:
<Button
android:id="@+id/btn_a"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="60%"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_default="percent"
app:layout_constraintWidth_percent="0.6" />
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="30%"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_a"
app:layout_constraintWidth_default="percent"
app:layout_constraintWidth_percent="0.3" />

1.3 宽高比约束
ConstraintLayout支持宽高比方式来约束,同样是将控件宽度或高度设置为0dp(即MATCH_CONSTRAINT),然后根据属性layout_constraintDimensionRatio设置宽高比。
属性layout_constraintDimensionRatio支持值有:
- 比率;
- 具体浮点数;
- 指定比值的分子是宽或高
XML代码:
<?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_ratio_1"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_marginTop="20dp"
android:text="宽高比约束(比率1:1)"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_ratio_2"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_marginStart="20dp"
android:layout_marginTop="20dp"
android:text="宽高比约束(比率1:2)"
app:layout_constraintDimensionRatio="1:2"
app:layout_constraintStart_toEndOf="@+id/btn_ratio_1"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_ratio_3"
android:layout_width="100dp"
android:layout_height="0dp"
android:layout_marginStart="20dp"
android:layout_marginTop="20dp"
android:text="宽高比约束(浮点数0.5)"
app:layout_constraintDimensionRatio="0.5"
app:layout_constraintStart_toEndOf="@+id/btn_ratio_2"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_ratio_4"
android:layout_width="0dp"
android:layout_height="110dp"
android:layout_marginStart="20dp"
android:layout_marginTop="20dp"
android:text="宽高比约束(W,10:5)"
app:layout_constraintDimensionRatio="W,10:5"
app:layout_constraintStart_toEndOf="@+id/btn_ratio_3"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_ratio_5"
android:layout_width="0dp"
android:layout_height="200dp"
android:layout_marginStart="20dp"
android:layout_marginTop="20dp"
android:text="宽高比约束(H,10:5)"
app:layout_constraintDimensionRatio="H,10:5"
app:layout_constraintEnd_toEndOf="@id/btn_ratio_4"
app:layout_constraintStart_toEndOf="@+id/btn_ratio_3"
app:layout_constraintTop_toBottomOf="@+id/btn_ratio_4" />
</androidx.constraintlayout.widget.ConstraintLayout>
示意图:

2. 链约束
链是一组视图,使用链约束可以把一组视图水平或垂直控制,十分高效和方便。
<Button
android:id="@+id/btn_a"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="A"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/btn_b"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_b"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="B"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/btn_a"
app:layout_constraintTop_toTopOf="parent" />

示意图中按钮A和按钮B具有双向约束,它们构成一个链。其中按钮A为链头,该链属性由链头A控制。
链具有多种样式:
- spread:默认样式,将链中元素全部展开,均匀分布,两端有间距;
- spread_inside:链中元素全部展开,但两端无间距;
- weighted:权重链,为链中每个元素占用的权重设置大小;
- packed:链中元素居中聚在一起,两端间距相同;
- packed bias:链中元素聚在一起,根据水平或垂直的偏差bias属性控制偏移。
权重链使用属性:layout_constraintHorizontal_weight或layout_constraintVertical_weight来控制元素占用空间大小。
下面是关键代码示例:
<Button
android:id="@+id/btn_a"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="A"
app:layout_constraintEnd_toStartOf="@id/btn_b"
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_b"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="B"
app:layout_constraintEnd_toStartOf="@id/btn_c"
app:layout_constraintStart_toEndOf="@id/btn_a"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_c"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="C"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/btn_b"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_a_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="A"
app:layout_constraintEnd_toStartOf="@id/btn_b_1"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_a" />
<Button
android:id="@+id/btn_b_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="B"
app:layout_constraintEnd_toStartOf="@id/btn_c_1"
app:layout_constraintStart_toEndOf="@id/btn_a_1"
app:layout_constraintTop_toBottomOf="@id/btn_a" />
<Button
android:id="@+id/btn_c_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="C"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/btn_b_1"
app:layout_constraintTop_toBottomOf="@id/btn_a" />
<Button
android:id="@+id/btn_a_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="A"
app:layout_constraintEnd_toStartOf="@id/btn_b_2"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_a_1" />
<Button
android:id="@+id/btn_b_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="B"
app:layout_constraintEnd_toStartOf="@id/btn_c_2"
app:layout_constraintStart_toEndOf="@id/btn_a_2"
app:layout_constraintTop_toBottomOf="@id/btn_a_1" />
<Button
android:id="@+id/btn_c_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="C"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/btn_b_2"
app:layout_constraintTop_toBottomOf="@id/btn_a_1" />
<Button
android:id="@+id/btn_a_3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="A"
app:layout_constraintEnd_toStartOf="@id/btn_b_3"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_a_2" />
<Button
android:id="@+id/btn_b_3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="B"
app:layout_constraintEnd_toStartOf="@id/btn_c_3"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintStart_toEndOf="@id/btn_a_3"
app:layout_constraintTop_toBottomOf="@id/btn_a_2" />
<Button
android:id="@+id/btn_c_3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="C"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_weight="3"
app:layout_constraintStart_toEndOf="@id/btn_b_3"
app:layout_constraintTop_toBottomOf="@id/btn_a_2" />
<Button
android:id="@+id/btn_a_4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="A"
app:layout_constraintEnd_toStartOf="@id/btn_b_4"
app:layout_constraintHorizontal_bias="0.3"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_a_3" />
<Button
android:id="@+id/btn_b_4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="B"
app:layout_constraintEnd_toStartOf="@id/btn_c_4"
app:layout_constraintStart_toEndOf="@id/btn_a_4"
app:layout_constraintTop_toBottomOf="@id/btn_a_3" />
<Button
android:id="@+id/btn_c_4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="C"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/btn_b_4"
app:layout_constraintTop_toBottomOf="@id/btn_a_3" />
示意图:

【注意❗】
使用链约束时要注意链两端元素,只有链每一端都被约束都同一轴上(水平或垂直)的另一个对象时,链才能启作用。
浙公网安备 33010602011771号