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。