使用 ConstraintLayout 构建响应式界面 Android Jetpack 的一部分。

试用 Compose 方式
Jetpack Compose 是推荐在 Android 设备上使用的界面工具包。了解如何在 Compose 中使用布局。
<ph type="x-smartling-placeholder"></ph> Compose 中的 ConstraintLayout →

ConstraintLayout 可让您使用扁平视图层次结构创建复杂的大型布局, 嵌套视图组。类似于 RelativeLayout 因为所有视图都是根据同级视图之间的关系 和父布局,但它比 RelativeLayout 更灵活 并且更易于与 Android Studio 的布局编辑器搭配使用。

ConstraintLayout 的所有强大功能均可直接通过 布局编辑器的可视化工具,因为布局 API 和布局编辑器 专为彼此打造的应用您可以使用 完全ConstraintLayout,无需修改 XML。

本页介绍了如何使用 ConstraintLayout 构建布局 Android Studio 3.0 或更高版本。如需详细了解布局编辑器, 请参阅使用布局编辑器构建界面

如需查看您可以使用 ConstraintLayout 创建的各种布局, 请参阅 GitHub 上的约束布局示例项目

约束条件概览

如需在 ConstraintLayout 中定义视图的位置,请在代码中添加 为视图设置至少一个水平约束条件和一个垂直约束条件。每个限制条件 表示与其他视图、父布局或 无形的指导方针。每个约束条件都定义了视图沿着 纵轴或横轴。每个视图都必须至少有一个约束条件 但通常要用到更多数据

将视图拖放到布局编辑器中后,它会一直保留在您放置的位置 如果没有任何限制,则会发生此错误。这样做只是为了方便您进行修改。如果视图没有 当您在设备上运行布局时,它会在位置 [0,0] 处绘制。 (左上角)。

在图 1 中,布局在编辑器中看起来很棒,但没有垂直 对视图 C 的约束。当此布局在设备上绘制时,水平视图 C 与视图 A 的左边缘和右边缘对齐,但它位于 因为它没有垂直约束条件

图 1. 编辑器将视图 C 显示在视图 A 下方, 没有垂直约束条件。

图 2. 视图 C 现在受到垂直约束 (位于视图 A 下方)。

尽管缺少约束条件不会导致编译错误,但布局 编辑器在工具栏中将缺少约束条件指出为错误。要查看 错误和其他警告,请点击显示警告和错误 。 为了帮助您避免缺少约束条件,布局编辑器会自动添加 使用 自动连接和推断约束条件 功能。

将 ConstraintLayout 添加到项目中

如需在您的项目中使用 ConstraintLayout,请按以下步骤操作:

  1. 确保您已声明 maven.google.com 代码库 在 settings.gradle 文件中:

    Groovy

        dependencyResolutionManagement {
          ...
          repositories {
              google()
          }
        )
        

    Kotlin

        dependencyResolutionManagement {
          ...
          repositories {
              google()
          }
        }
        
  2. 将该库作为依赖项添加到模块级 build.gradle 文件,如以下示例所示。最新 可能与示例中显示的版本不同。

    Groovy

    dependencies {
        implementation "androidx.constraintlayout:constraintlayout:2.2.0-alpha14"
        // To use constraintlayout in compose
        implementation "androidx.constraintlayout:constraintlayout-compose:1.1.0-alpha14"
    }
    

    Kotlin

    dependencies {
        implementation("androidx.constraintlayout:constraintlayout:2.2.0-alpha14")
        // To use constraintlayout in compose
        implementation("androidx.constraintlayout:constraintlayout-compose:1.1.0-alpha14")
    }
    
  3. 在工具栏或同步通知中,点击 Sync Project with Gradle 文件

现在,您可以使用 ConstraintLayout 构建布局。

转换布局

图 3. 要将布局转换为的菜单 ConstraintLayout

如需将现有布局转换为约束布局,请按以下步骤操作:

  1. 在 Android Studio 中打开布局,然后点击 Design 标签页 位于编辑器窗口底部
  2. Component Tree 窗口中,右键点击该布局,然后点击 将 LinearLayout 转换为 ConstraintLayout

创建新布局

如需开始新的约束布局文件,请按以下步骤操作:

  1. Project 窗口中,点击模块文件夹并选择 文件 >新建 >XML >布局 XML
  2. 输入布局文件的名称,然后输入 “androidx.constraintlayout.widget.ConstraintLayout”对于根 代码
  3. 点击 Finish

添加或移除约束条件

如需添加约束条件,请执行以下操作:

视频 1. 视图的左侧被约束为左侧 父元素。

  1. 将视图从 Palette 窗口拖到编辑器中。

    ConstraintLayout 中添加视图后,该视图会显示在 每个角上都有用于调整大小的方形手柄和圆形的边界框 约束手柄。

  2. 点击视图将其选中。
  3. 请执行以下某项操作: <ph type="x-smartling-placeholder">
      </ph>
    • 点击约束手柄并将其拖动到可用的定位点。 此点可以是另一个视图的边缘、布局的边缘,也可以是 指南。请注意,当您拖动约束手柄时,布局 编辑器显示可能的连接锚点和蓝色叠加层。
    • 点击其中一个创建连接 Attributes 窗口的 Layout 部分中的按钮,如下所示: 如图 4 所示。

      图 4. 布局 Attributes 窗口的这一部分,您可以创建 连接。

创建限制条件后,编辑器会为其指定 default margin 来分隔两个视图。

创建约束条件时,请注意以下规则:

  • 每个视图必须至少有两个约束条件:一个水平约束条件 。
  • 您只能在约束手柄和锚点之间创建约束条件。 它们位于同一平面垂直平面(左侧和右侧) 侧面 - 只能约束在另一个垂直平面上,以及 基线只能约束其他基线。
  • 每个约束手柄只能用于一个约束条件,但您可以 创建从不同视图到同一定位点的多个约束条件。

您可以通过执行以下任一操作来删除约束条件:

  • 点击某个限制条件以将其选中,然后点击删除
  • 按住 Ctrl 键的同时点击(在 macOS 上,则是在 Command 键的同时点击鼠标) 约束锚点。该约束条件将变为红色,表示您可以点击 如图 5 所示。

    图 5. 红色的约束条件表示 点击该图标即可将其删除

  • Attributes 窗口的 Layout 部分中,点击 约束锚点,如图 6 所示。

    图 6. 点击限制条件 以便将其删除。

视频 2. 添加与现有约束条件相反的约束条件。

如果向视图添加相反的约束条件,则约束行会变为 像弹簧一样卷曲来表示对立的力,如视频 2 所示。通过 当视图大小设置为“fixed”时,效果最明显或“封装内容” 在这种情况下,视图位于约束条件之间。如果您想改为 视图扩展尺寸以满足约束条件, 将尺寸切换为“match constraints”如果 您想要保持当前尺寸,但移动视图,使其不居中, 调整约束偏差

您可以使用约束条件来实现不同类型的布局行为,例如 具体说明。

父级位置

将视图的一侧约束到布局的相应边缘。

在图 7 中,视图的左侧与 父布局。您可以使用外边距来定义与边缘的距离。

图 7. 父级对象。

顺序位置

定义两个视图的显示顺序,垂直或 水平。

在图 8 中,B 被约束为始终位于 A 的右侧,而 C 则 限制在 A 以下。不过,这些限制并不意味着对齐,因此 B 可以

图 8. “水平”和“垂直” 限制条件。

对齐方式

将一个视图的边缘与另一视图的同一边对齐。

在图 9 中,B 的左侧与 A 的左侧对齐。如果您想 为了与视图中心对齐,请在两侧创建一个约束条件。

您可以通过从约束条件向内拖动视图来偏移对齐。 例如,图 10 显示 B 的偏移对齐为 24dp。偏移为 由受约束的视图的外边距定义。

您也可以选择所有想要对齐的视图,然后点击 对齐 可以选择对齐类型。

图 9. 水平对齐 限制条件。

图 10. 水平偏移量 对齐约束。

基线对齐

将一个视图的文本基线与另一视图的文本基线对齐。

在图 11 中,B 的第一行与 A 中的文本对齐。

要创建基线约束条件,请右键点击 约束条件,然后点击 Show Baseline。然后点击文本 并将线条拖动到另一条基线上。

图 11. 基线对齐 限制条件。

引导线约束

您可以添加垂直或水平的引导线 对应用用户不可见。您可以将准则 基于 dp 单位或相对于 布局边缘。

如需创建准则,请点击准则 ,然后点击 Add Vertical Guideline(添加行业引导线)或 Add(添加) 水平准则

拖动虚线以调整位置,然后点击 切换衡量模式的指南。

图 12. 约束为 指南。

屏障约束

与准则类似,屏障是一条看不见的界线,您可以约束它 但屏障不会定义自己的位置。相反, position 会根据其中包含的视图的位置而移动。这是 当您想要将视图约束为一组视图(而不是一个视图)时非常有用 特定数据视图

例如,在图 13 中,视图 C 被约束在 屏障。该分界线设置为“end”(或右侧,从左到右 布局。屏障的移动取决于 位于视图 A 的右侧或视图 B 的最右侧。

如需创建屏障,请按以下步骤操作:

  1. 点击准则 ,然后点击 Add Vertical Barrier添加水平屏障
  2. Component Tree 窗口中,选择要放入 并将其拖动到屏障组件中。
  3. Component Tree 中选择屏障,打开 属性 然后设置 blockDirection

现在,您可以从另一个视图创建屏障约束。

您还可以将屏障内部的视图约束为 屏障。这样,您可以让屏障中的所有视图相互对齐, 即使不知道哪个视图最长或最高也没关系

您还可以在屏障内添加一个准则,以确保“最低” 也就是屏障的位置

图 13. 视图 C 被限制在一个屏障内, 它会根据视图 A 和视图 B 的位置和大小进行移动。

调整约束偏差

当您为视图两侧添加约束条件时 同一维度要么是“固定”或“wrap content”的情况下,视图会居中 偏差为 50%。您可以调整 拖动 Attributes 窗口中的偏差滑块或拖动 如视频 3 所示

如果您希望视图扩展其尺寸以满足约束条件, 将尺寸切换为“match constraints”

视频 3. 调整约束偏差。

调整视图尺寸

图 14. 选择视图时, Attributes 窗口包含 1 尺寸比, 2删除限制条件, 3 高度或宽度模式, 4 页外边距,以及 5 约束偏差。您还可以突出显示 通过在布局编辑器中点击各个约束条件 6 限制条件列表。

你可以使用角手柄来调整视图大小,但这会对 尺寸:视图不会针对不同的内容或屏幕尺寸调整大小。接收者 选择其他大小模式,点击视图并打开 Attributes 窗口。

Attributes 窗口顶部附近是视图检查器, 包括若干布局属性的控件,如图 14 所示。这是 仅适用于约束布局中的视图。

要更改高度和宽度的计算方式,请点击 标注的 3 表示的符号。 这些符号代表尺码模式,如下所示。点击符号即可切换 请在以下设置之间切换:

  • 固定:在以下文本框中指定具体尺寸或通过 调整编辑器中的视图大小。
  • Wrap Content:视图仅根据需要展开即可适应其 内容。
    • layout_boundWidth
    • 如果将此值设为 true,水平尺寸就会变为 并遵守限制条件。默认情况下,系统会将微件设置为 WRAP_CONTENT 不受限制条件的限制

  • Match Constraints:视图会尽可能扩展,以符合 各边的约束条件。不过,您 您可以使用以下属性和值修改该行为。这些 属性仅在您将视图宽度设置为“match constraints”时才会生效: <ph type="x-smartling-placeholder">
      </ph>
    • layout_constraintWidth_min

      该视图的最小宽度采用 dp 维度。

    • layout_constraintWidth_max

      该视图的最大宽度采用 dp 维度。

    不过,如果给定维度只有一个约束条件,则视图 会展开即可适应其内容。同时针对高度或宽度使用此模式 用于设置尺寸比

。 <ph type="x-smartling-placeholder">

将尺寸设置为比率

图 15. 视图设置为 16:9 的宽高比, 根据高度比率确定宽度

您可以将视图尺寸设置为某个比例,例如 16:9,但前提是 视图尺寸设置为“match constraints”(0dp)。要启用 点击 Toggle Aspect Ratio Constraint (callout) 图 14 中的 1) 并输入 宽高比为 width:height

如果宽度和高度均设置为“match constraints”,可以点击 切换宽高比限制,选择哪个维度基于 彼此之间的比率。视图检查器会指明哪个维度被设为 用实线连接各个边进行比对

例如,如果您将两边都设置为“match constraints”,点击切换 Aspect Ratio Constraint 将宽度设置为高度的比率。 整个尺寸由视图的高度决定, 如图 15 所示

调整视图外边距

要使视图间距均等,请点击外边距 为您添加到 布局。您对默认外边距所做的任何更改只会应用于

您可以在 Attributes 窗口中控制每个视图的外边距,方法是 点击各条约束条件线上的数字。在图 14 中, 标注 4 表明下外边距设为 16dp。

图 16. 工具栏的 Margin 按钮。

该工具提供的所有外边距均为 8dp 的倍数,用于帮助您对齐视图 Material Design 给出的 8dp 方形网格建议。

使用链控制线性组

图 17. 水平链包含 两种视图

链是一组视图,这些视图通过双向 排名限制条件。链中的视图可以分布 垂直或水平。

图 18. 各个连锁店的示例 样式。

链可以采用以下几种样式之一:

  1. Spread:在设置外边距后,视图会均匀分布 这是默认值。
  2. Spread internal:第一个和最后一个 View 附加到 其余两端相等, 分发。
  3. 加权:当链设置为 spread展开,您可以设置一个或多个 “match constraints”(0dp)。默认情况下,聊天室处于 会在设置为“match constraints”的各视图之间平均分配但是 您可以使用 layout_constraintHorizontal_weightlayout_constraintVertical_weight 属性。 这与 layout_weight 中的 线性布局: 权重值最高的视图获得的空间最大, 权重相同的视图将获得相同大小的空间。
  4. Packed:在计算外边距后,视图会打包在一起 。您可以调整整个链的偏差 - 向左或向右,或向上或 方法是将链的“head”观看偏差。

链的“头”view — 水平链中最左边的视图 (采用从左到右布局)和 垂直链中的最顶层视图 - 以 XML 格式定义链的样式。 不过,您可以在传播内部传播打包:选择链中的任意视图并点击链中的按钮

如需创建链,请执行以下操作,如视频 4 所示:

  1. 选择要包含在链中的所有视图。
  2. 右键点击其中一个视图。
  3. 选择
  4. 选择水平居中垂直居中

视频 4. 创建水平链。

在使用链时,您需要注意以下几点:

  • 视图可以同时属于水平链和垂直链,因此您可以 构建灵活的网格布局。
  • 只有当链的每一端都被约束为 另一个对象,如图 14 所示。
  • 虽然链的方向是垂直或水平的, 不会沿该方向对齐视图。为了在 链中的每个视图,还要添加其他约束条件,例如 对齐限制

自动创建约束条件

将约束条件置于布局中时,无需为每个视图添加约束条件, 您可以在布局编辑器中将每个视图移动到所需位置 然后点击 Infer Constraints(推断约束条件) 自动创建限制条件

Infer Constraints 扫描布局,以确定最有效的集合 所有视图的约束条件它会将视图约束为当前位置 同时提供灵活性您可能需要做出一些调整 按照您的预期针对不同屏幕尺寸和方向进行响应。

Autoconnect to Parent 是一项您可以启用的独立功能。时间 并且您将子视图添加到父视图后,此功能会自动 在您将视图添加到 但仅当适当地将视图约束到父视图时 布局。Autoconnect 不会为布局中的其他视图创建约束条件。

Autoconnect 在默认情况下处于停用状态。点击启用 自动连接到父级

关键帧动画

ConstraintLayout 中,您可以为大小变化添加动画效果 调整元素的位置和位置, ConstraintSetTransitionManager

ConstraintSet 是一个轻量级对象,代表 所有子元素的约束条件、外边距和内边距, ConstraintLayout。将 ConstraintSet 应用于 显示了 ConstraintLayout,布局会更新 所有子项。

如需使用 ConstraintSet 构建动画,请指定两种布局 用作动画开始和结束关键帧的文件然后,您可以 从第二个关键帧文件中获取的 ConstraintSet,并将其应用于 显示的ConstraintLayout

<ph type="x-smartling-placeholder">

以下代码示例展示了如何以动画方式将单个按钮移动到 屏幕底部。

// 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 用于 向日葵 演示版应用。