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 中有专门的百分比布局方式——PercentFrameLayoutPercentRelativeLayout,但早已被废弃。ConstraintLayout 支持百分比布局,现代的百分比布局方式更加推荐使用ConstraintLayout。实现步骤如下:

  1. layout_width或layout_height设置为0dp(MATCH_CONSTRAINT);
  2. 设置layout_constraintWidth_default="percent"或layout_constraintHeight_default="percent";
  3. 使用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_weightlayout_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" />

示意图:

链约束样式

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

3. 参考资料

posted @ 2026-09-05 09:53  换元不配限  阅读(5)  评论(0)    收藏  举报