使用 ConstraintLayout 构建响应式界面 Android Jetpack 的组成部分。
ConstraintLayout
可让您创建包含平面视图层次结构(无嵌套视图组)的大型复杂布局。它与 RelativeLayout
类似,所有视图均根据同级视图和父级布局之间的关系进行布局,但它比 RelativeLayout
更灵活,也更易于在 Android Studio 的 Layout Editor 中使用。
ConstraintLayout
的所有功能都可以直接从 Layout Editor 的可视化工具中使用,因为布局 API 和 Layout Editor 是专门为彼此构建的。您可以通过拖动而不是编辑 XML 来完全使用 ConstraintLayout
构建布局。
本页面介绍如何在 Android Studio 3.0 或更高版本中使用 ConstraintLayout
构建布局。如需详细了解 Layout Editor,请参阅使用 Layout Editor 构建界面。
如需查看可以使用 ConstraintLayout
创建的各种布局,请参阅 GitHub 上的 Constraint Layout Examples 项目。
约束概览
要在 ConstraintLayout
中定义视图的位置,您需要为该视图至少添加一个水平约束和一个垂直约束。每个约束代表与其他视图、父级布局或不可见辅助线的连接或对齐。每个约束沿垂直或水平轴定义视图的位置。每个视图必须至少有一个轴上的约束,但通常需要更多约束。
当您将视图拖放到 Layout Editor 中时,即使视图没有约束,它也会保留在您放置的位置。这仅是为了方便编辑。如果在设备上运行布局时视图没有约束,它将被绘制在位置 [0,0](左上角)。
在图 1 中,布局在编辑器中看起来不错,但视图 C 没有垂直约束。当此布局在设备上绘制时,视图 C 会与视图 A 的左侧和右侧边缘水平对齐,但会显示在屏幕顶部,因为它没有垂直约束。

图 1. 编辑器中视图 C 显示在视图 A 下方,但它没有垂直约束。

图 2. 视图 C 现在在视图 A 下方受到垂直约束。
虽然缺少约束不会导致编译错误,但 Layout Editor 会在工具栏中将缺少约束标记为错误。要查看错误和其他警告,请点击显示警告和错误 。为了帮助您避免缺少约束,Layout Editor 会使用自动连接和推断约束功能为您自动添加约束。
将 ConstraintLayout 添加到项目
要在项目中使用 ConstraintLayout
,请按如下步骤操作:
- 确保您在
settings.gradle
文件中声明了maven.google.com
代码库Groovy
dependencyResolutionManagement { ... repositories { google() } )
Kotlin
dependencyResolutionManagement { ... repositories { google() } }
- 将该库作为依赖项添加到模块级
build.gradle
文件中,如以下示例所示。最新版本可能与示例中显示的版本不同。Groovy
dependencies { implementation "androidx.constraintlayout:constraintlayout:2.2.1" // To use constraintlayout in compose implementation "androidx.constraintlayout:constraintlayout-compose:1.1.1" }
Kotlin
dependencies { implementation("androidx.constraintlayout:constraintlayout:2.2.1") // To use constraintlayout in compose implementation("androidx.constraintlayout:constraintlayout-compose:1.1.1") }
- 在工具栏或同步通知中,点击将项目与 Gradle 文件同步。
现在,您已准备好使用 ConstraintLayout
构建布局。
转换布局

图 3. 将布局转换为 ConstraintLayout
的菜单。
要将现有布局转换为约束布局,请按照以下步骤操作:
- 在 Android Studio 中打开布局,然后点击编辑器窗口底部的设计标签页。
- 在组件树窗口中,右键点击布局,然后点击将 LinearLayout 转换为 ConstraintLayout。
创建新布局
要创建新的约束布局文件,请按照以下步骤操作:
- 在项目窗口中,点击模块文件夹,然后选择文件 > 新建 > XML > Layout XML。
- 输入布局文件的名称,然后在根标签中输入 "androidx.constraintlayout.widget.ConstraintLayout"。
- 点击完成。
添加或移除约束
要添加约束,请按如下步骤操作:
视频 1. 视图的左侧约束到父级的左侧。
将视图从组件面板窗口拖到编辑器中。
当您在
ConstraintLayout
中添加视图时,它会显示在一个边界框中,每个角都有方形大小调整手柄,每条边都有圆形约束手柄。- 点击视图以将其选中。
- 执行以下任一操作:
- 点击约束手柄并将其拖动到可用锚点。该点可以是另一个视图的边缘、布局的边缘或辅助线。请注意,当您拖动约束手柄时,Layout Editor 会显示潜在的连接锚点和蓝色叠加层。
点击属性窗口布局部分中的一个创建连接
按钮,如图 4 所示。
图 4. 属性窗口的布局部分可让您创建连接。
创建约束后,编辑器会为其指定一个默认边距以分隔两个视图。
创建约束时,请记住以下规则:
- 每个视图必须至少有两个约束:一个水平约束和一个垂直约束。
- 您只能在约束手柄和共享同一平面的锚点之间创建约束。视图的垂直平面(左侧和右侧)只能约束到另一个垂直平面,而基线只能约束到其他基线。
- 每个约束手柄只能用于一个约束,但您可以从不同的视图创建多个约束到同一个锚点。
您可以通过执行以下任一操作来删除约束:
- 点击约束以将其选中,然后点击 Delete。
按住 Control 键(在 macOS 上按 Command 键)并点击约束锚点。约束会变成红色,表示您可以点击以删除它,如图 5 所示。
图 5. 红色约束表示您可以点击以删除它。
在属性窗口的布局部分,点击约束锚点,如图 6 所示。
图 6. 点击约束锚点以将其删除。
视频 2. 添加与现有约束相反的约束。
如果您在一个视图上添加相反的约束,约束线会像弹簧一样卷曲,以表示相反的作用力,如视频 2 所示。当视图大小设置为“固定”或“内容适配”时,这种效果最明显,在这种情况下,视图会居中于约束之间。如果您希望视图拉伸其大小以满足约束,请将大小切换为“匹配约束”。如果您希望保持当前大小,但移动视图使其不居中,请调整约束偏差。
您可以使用约束来实现不同类型的布局行为,如下面几节所述。
父级位置
将视图的一侧约束到布局的相应边缘。
在图 7 中,视图的左侧连接到父级布局的左边缘。您可以使用边距定义距离边缘的距离。

图 7. 对父级的水平约束。
顺序位置
定义两个视图的显示顺序,可以是垂直或水平顺序。
在图 8 中,B 约束为始终在 A 的右侧,C 约束在 A 的下方。但是,这些约束并不意味着对齐,因此 B 仍然可以上下移动。

图 8. 水平和垂直约束。
对齐
将视图的边缘与另一个视图的相同边缘对齐。
在图 9 中,B 的左侧与 A 的左侧对齐。如果您想对齐视图中心,请在两侧创建约束。
您可以通过将视图从约束处向内拖动来偏移对齐。例如,图 10 显示 B 具有 24dp 的偏移对齐。偏移由受约束视图的边距定义。
您还可以选择所有要对齐的视图,然后点击工具栏中的对齐 以选择对齐类型。

图 9. 水平对齐约束。

图 10. 偏移的水平对齐约束。
基线对齐
将视图的文本基线与另一个视图的文本基线对齐。
在图 11 中,B 的第一行与 A 中的文本对齐。
要创建基线约束,请右键点击要约束的文本视图,然后点击显示基线。然后点击文本基线并将线条拖动到另一个基线。

图 11. 基线对齐约束。
约束到辅助线
您可以添加垂直或水平辅助线,用于约束您的视图,并且对应用用户不可见。您可以根据 dp 单位或相对于布局边缘的百分比在布局中定位辅助线。
要创建辅助线,请点击工具栏中的辅助线 ,然后点击添加垂直辅助线或添加水平辅助线。
拖动虚线以重新定位它,然后点击辅助线边缘的圆圈以切换测量模式。

图 12. 约束到辅助线的视图。
约束到屏障
类似于辅助线,屏障是一条不可见的线,您可以将视图约束到它,但屏障不定义自己的位置。相反,屏障的位置会根据其中包含的视图的位置移动。当您希望将视图约束到一组视图而不是一个特定视图时,这很有用。
例如,在图 13 中,视图 C 约束到屏障的右侧。屏障被设置为视图 A 和视图 B 的“末端”(或从左到右布局中的右侧)。屏障会根据视图 A 或视图 B 的右侧哪个最靠右而移动。
要创建屏障,请按照以下步骤操作:
- 点击工具栏中的辅助线
,然后点击添加垂直屏障或添加水平屏障。
- 在组件树窗口中,选择您希望位于屏障内的视图,然后将它们拖到屏障组件中。
- 从组件树中选择屏障,打开属性
窗口,然后设置 barrierDirection。
现在,您可以从另一个视图创建约束到该屏障。
您还可以将位于屏障内部的视图约束到屏障。这样,您可以将屏障中的所有视图相互对齐,即使您不知道哪个视图最长或最高。
您还可以在屏障内包含辅助线,以确保屏障具有“最小”位置。

图 13. 视图 C 约束到屏障,屏障会根据视图 A 和视图 B 的位置和大小而移动。
调整约束偏差
当您为一个视图的两侧添加约束,并且视图在同一维度上的大小设置为“固定”或“内容适配”时,视图默认会以 50% 的偏差居中于两个约束之间。您可以通过拖动属性窗口中的偏差滑块或拖动视图来调整偏差,如视频 3 所示。
如果您希望视图拉伸其大小以满足约束,请将大小切换为“匹配约束”。
如果您希望保持当前大小,但移动视图使其不居中,请调整约束偏差。
视频 3. 调整约束偏差。

调整视图大小
图 14. 选择视图时,属性窗口包含用于调整 1 尺寸比例、2 删除约束、3 高度或宽度模式、4 边距以及 5 约束偏差的控件。您还可以通过在 6 约束列表中点击 Layout Editor 中的单个约束来高亮显示它们。
您可以使用角手柄调整视图大小,但这会硬编码大小 - 视图不会针对不同的内容或屏幕尺寸进行调整。要选择不同的尺寸模式,请点击视图并打开编辑器右侧的属性 窗口。
属性窗口顶部附近是视图检查器,其中包含多个布局属性的控件,如图 14 所示。此功能仅适用于约束布局中的视图。
- 您可以通过点击图 14 中用标注 3 指示的符号来更改高度和宽度的计算方式。这些符号表示尺寸模式如下。点击符号可在这些设置之间切换:
-
固定:在以下文本框中指定特定尺寸,或通过在编辑器中调整视图大小来指定。
内容适配:视图仅根据需要扩展以适应其内容。
-
将此值设置为
true
可让水平尺寸根据约束进行更改。默认情况下,设置为WRAP_CONTENT
的微件不受约束限制。匹配约束:视图会尽可能扩展以满足两侧的约束,同时考虑到视图的边距。但是,您可以使用以下属性和值修改该行为。这些属性仅在将视图宽度设置为“匹配约束”时生效
layout_constraintWidth_min
- 此属性接受视图最小宽度的
dp
尺寸值。layout_constraintWidth_max
此属性接受视图最大宽度的
dp
尺寸值。
layout_constrainedWidth
注意:您不能在 ConstraintLayout
中的任何视图上使用 match_parent
。请改为使用“匹配约束”(0dp
)。

将尺寸设置为比例
图 15. 视图设置为 16:9 的宽高比,宽度基于高度的比例。
如果视图的至少一个维度设置为“匹配约束”(0dp
),您可以将视图尺寸设置为比例,例如 16:9。要启用比例,请点击切换宽高比约束(图 14 中的标注 1),然后在出现的输入框中输入 width:height 比例。
如果宽度和高度都设置为“匹配约束”,您可以双击切换宽高比约束,将宽度设置为高度的比例。整个尺寸由视图的高度决定,高度可以通过任何方式定义,如图 15 所示。
调整视图边距
要使您的视图均匀间隔,请点击工具栏中的边距 ,为添加到布局中的每个视图选择默认边距。您对默认边距所做的任何更改仅适用于此后添加的视图。
您可以通过点击代表每个约束的线上的数字,在属性窗口中控制每个视图的边距。在图 14 中,标注 4 显示底部边距设置为 16dp。
图 16. 工具栏的边距按钮。
该工具提供的所有边距都是 8dp 的倍数,以帮助您的视图对齐 Material Design 的 8dp 方格网格建议。
使用链控制线性组

图 17. 包含两个视图的水平链。
链是一组通过双向位置约束相互连接的视图。链内的视图可以垂直或水平分布。

图 18. 每种链样式的示例。
链可以通过以下方式设置样式:
- 分散:视图在考虑边距后均匀分布。这是默认设置。
- 内部分散:第一个和最后一个视图固定在链两端的约束上,其余视图均匀分布。
- 加权:当链设置为分散或内部分散时,您可以通过将一个或多个视图设置为“匹配约束”(
0dp
) 来填充剩余空间。默认情况下,空间在每个设置为“匹配约束”的视图之间均匀分布,但您可以使用layout_constraintHorizontal_weight
和layout_constraintVertical_weight
属性为每个视图分配重要性权重。这与线性布局中的layout_weight
工作方式相同:权重值最高的视图获得的空间最多,具有相同权重的视图获得相同数量的空间。 - 打包:视图在考虑边距后打包在一起。您可以通过更改链的“头部”视图偏差来调整整个链的偏差 - 向左或向右,向上或向下。
链的“头部”视图 - 水平链中最左边的视图(在从左到右的布局中)和垂直链中最顶部的视图 - 在 XML 中定义链的样式。但是,您可以通过选择链中的任何视图并点击视图下方出现的链按钮 在分散、内部分散和打包之间切换。
要创建链,请按如下步骤操作,如视频 4 所示:
- 选择所有要包含在链中的视图。
- 右键点击其中一个视图。
- 选择链。
- 选择水平居中或垂直居中。
视频 4. 创建水平链。
使用链时需要考虑以下几点:
- 视图可以同时属于水平链和垂直链,因此您可以构建灵活的网格布局。
- 链只有在链的每一端都约束到同一轴上的另一个对象时才能正常工作,如图 14 所示。
- 虽然链的方向是垂直或水平的,但使用链并不会在该方向上对齐视图。要使链中的每个视图都获得正确的位置,请包含其他约束,例如对齐约束。
自动创建约束
您无需在将每个视图放置到布局中时都为其添加约束,而是可以在 Layout Editor 中将每个视图移动到您想要的位置,然后点击推断约束 以自动创建约束。
推断约束会扫描布局,以确定所有视图的最有效约束集。它将视图约束到其当前位置,同时提供灵活性。您可能需要进行调整,以使布局根据您的意图响应不同的屏幕尺寸和方向。
自动连接到父级是您可以启用的一个独立功能。启用此功能并在向父级添加子视图时,它会在您将每个视图添加到布局时自动为其创建两个或更多约束 - 但仅当适合将视图约束到父级布局时才会创建。自动连接不会创建与其他视图的约束。
自动连接默认处于禁用状态。通过点击 Layout Editor 工具栏中的启用自动连接到父级 来启用它。
关键帧动画
在 ConstraintLayout
中,您可以使用 ConstraintSet
和 TransitionManager
为元素的大小和位置变化添加动画。
一个 ConstraintSet
是一个轻量级对象,表示 ConstraintLayout
中所有子元素的约束、边距和内边距。当您将 ConstraintSet
应用于显示的 ConstraintLayout
时,布局会更新其所有子项的约束。
要使用 ConstraintSet
构建动画,请指定两个布局文件作为动画的开始和结束关键帧。然后,您可以从第二个关键帧文件加载 ConstraintSet
并将其应用于显示的 ConstraintLayout
。
以下代码示例展示了如何动画化将单个按钮移动到屏幕底部。
// MainActivity.kt
fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.keyframe_one)
constraintLayout = findViewById(R.id.constraint_layout) // member variable
}
fun animateToKeyframeTwo() {
val constraintSet = ConstraintSet()
constraintSet.load(this, R.layout.keyframe_two)
TransitionManager.beginDelayedTransition()
constraintSet.applyTo(constraintLayout)
}
// layout/keyframe1.xml // Keyframe 1 contains the starting position for all elements in the animation // as well as final colors and text sizes. <?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/button2" android:layout_width="0dp" android:layout_height="wrap_content" android:text="Button" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
// layout/keyframe2.xml // Keyframe 2 contains another ConstraintLayout with the final positions. <?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/button2" android:layout_width="0dp" android:layout_height="wrap_content" android:text="Button" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintBottom_toBottomOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
其他资源
ConstraintLayout
在 Sunflower 演示应用中使用。