ConstraintLayout:表达关系而不是堆嵌套 · AndroidX 源码指南
AAndroidX 源码指南
View 体系
View 体系 · androidx.core

ConstraintLayout:表达关系而不是堆嵌套Core 1.20.0-alpha01

用双向约束、Guideline、Barrier、ConstraintSet 管理复杂 View 布局。

最后更新 2026-08-01

复制即用:基础约束

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/title"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

关键概念:约束方向用 0dp = match constraints(尺寸由两端约束决定),不是宽度为零。

常用属性

属性作用
layout_constraintStart_toStartOf/End_toEndOf水平对齐
layout_constraintTop_toTopOf/Bottom_toBottomOf垂直对齐
layout_constraintWidth_percent="0.5"宽度百分比
layout_constraintHorizontal_bias="0.3"水平偏向
layout_constraintChainStyle链样式(spread/packed/weighted)

规则:每个 View 在水平和垂直方向都要有足够约束,否则编辑器预览和运行时位置不一致。

Guideline:参考线

<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" />

<!-- 使用 -->
<TextView
    app:layout_constraintStart_toStartOf="@id/guideline"
    ... />
  • 固定(layout_constraintGuide_begin)或百分比(_percent)参考线。
  • 适合左右分栏、居中分割。

Barrier:随内容自适应

<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="title,subtitle" />
  • 根据一组 View 的实际边缘定位。
  • 适合文本长度变化时的布局(标题/副标题长度不定)。

ConstraintSet:运行时切换整套关系

val set = ConstraintSet()
set.clone(layout)                 // 从当前布局克隆
set.constrainWidth(R.id.title, ConstraintSet.MATCH_CONSTRAINT)
set.setGuidelinePercent(R.id.guideline, 0.7f)
set.applyTo(layout)               // 应用

// 动画切换
TransitionManager.beginDelayedTransition(layout)
set.applyTo(layout)

不要逐个改 LayoutParams 形成难以回滚的半状态——用 ConstraintSet 整体切换。

Compose 场景

Compose 有独立 constraintlayout-compose artifact,但简单布局优先 Row/Column/Box:

// 只有跨多个元素的复杂关系才用约束 DSL
ConstraintLayout {
    val title = createRefFor("title")
    Text("标题", Modifier.constrainAs(title) {
        top.linkTo(parent.top)
        start.linkTo(parent.start)
    })
}

常见陷阱

  • 约束不完整:某方向无约束 → 位置不确定。
  • 0dp 误解:match constraints ≠ 0 宽度。
  • 嵌套过多:用 ConstraintLayout 代替 LinearLayout 嵌套。
  • 运行时半状态:别逐属性改 LayoutParams,用 ConstraintSet。
  • 简单布局用约束:Compose 里 Row/Column 更直接。

复制即用

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/title"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />

    <Button
        android:id="@+id/action"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@id/title"
        app:layout_constraintEnd_toEndOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

要点

  • 约束表达关系,替代嵌套 LinearLayout;0dp = match constraints。
  • Guideline 参考线、Barrier 内容自适应、Chain 组链。
  • ConstraintSet 运行时整体切换关系(可配合动画)。
  • Compose 简单布局用 Row/Column,复杂关系才用约束 DSL。

相关页面