ConstraintLayout
是一种布局,允许您将可组合项相对于屏幕上的其他可组合项进行放置。它是使用多个嵌套 Row
、Column
、Box
和 其他自定义布局元素 的替代方案。ConstraintLayout
在实现具有更复杂对齐要求的大型布局时非常有用。
考虑在以下情况下使用 ConstraintLayout
- 为了避免嵌套多个
Column
和Row
来定位屏幕上的元素,从而提高代码的可读性。 - 为了将可组合项相对于其他可组合项进行定位,或者根据指南、障碍或链来定位可组合项。
在 View 系统中,ConstraintLayout
是创建大型和复杂布局的推荐方法,因为扁平的视图层次结构比嵌套视图的性能更好。但是,这在 Compose 中不是问题,Compose 能够有效地处理深层布局层次结构。
开始使用 ConstraintLayout
要在 Compose 中使用 ConstraintLayout
,您需要在您的 build.gradle
中添加此依赖项(除了 Compose 设置 之外)
implementation "androidx.constraintlayout:constraintlayout-compose:1.0.1"
Compose 中的 ConstraintLayout
使用 DSL 以以下方式工作
- 使用
createRefs()
或createRefFor()
为ConstraintLayout
中的每个可组合项创建引用。 - 约束条件使用
constrainAs()
修饰符提供,该修饰符将引用作为参数,并允许您在主体 lambda 中指定其约束条件。 - 约束条件使用
linkTo()
或其他有用的方法指定。 parent
是一个现有的引用,可用于指定针对ConstraintLayout
可组合项本身的约束条件。
这是一个使用 ConstraintLayout
的可组合项示例
@Composable fun ConstraintLayoutContent() { ConstraintLayout { // Create references for the composables to constrain val (button, text) = createRefs() Button( onClick = { /* Do something */ }, // Assign reference "button" to the Button composable // and constrain it to the top of the ConstraintLayout modifier = Modifier.constrainAs(button) { top.linkTo(parent.top, margin = 16.dp) } ) { Text("Button") } // Assign reference "text" to the Text composable // and constrain it to the bottom of the Button composable Text( "Text", Modifier.constrainAs(text) { top.linkTo(button.bottom, margin = 16.dp) } ) } }
此代码将 Button
的顶部约束到父级,边距为 16.dp
,并将 Text
约束到 Button
的底部,边距也为 16.dp
。
解耦 API
在 ConstraintLayout
示例中,约束条件是内联指定的,在应用它们的组合项中使用修饰符。但是,在某些情况下,最好将约束条件与其应用到的布局解耦。例如,您可能希望根据屏幕配置更改约束条件,或在两个约束集之间进行动画。
对于这种情况,您可以以不同的方式使用 ConstraintLayout
- 将
ConstraintSet
作为参数传递给ConstraintLayout
。 - 使用
layoutId
修饰符将ConstraintSet
中创建的引用分配给可组合项。
@Composable fun DecoupledConstraintLayout() { BoxWithConstraints { val constraints = if (minWidth < 600.dp) { decoupledConstraints(margin = 16.dp) // Portrait constraints } else { decoupledConstraints(margin = 32.dp) // Landscape constraints } ConstraintLayout(constraints) { Button( onClick = { /* Do something */ }, modifier = Modifier.layoutId("button") ) { Text("Button") } Text("Text", Modifier.layoutId("text")) } } } private fun decoupledConstraints(margin: Dp): ConstraintSet { return ConstraintSet { val button = createRefFor("button") val text = createRefFor("text") constrain(button) { top.linkTo(parent.top, margin = margin) } constrain(text) { top.linkTo(button.bottom, margin) } } }
然后,当您需要更改约束条件时,只需传递不同的 ConstraintSet
即可。
ConstraintLayout
概念
ConstraintLayout
包含诸如指南、障碍和链之类的概念,这些概念可以帮助您在可组合项内定位元素。
指南
指南是用于设计布局的小型可视化辅助工具。可组合项可以约束到指南。指南对于在父可组合项内某个 dp
或 百分比
处定位元素非常有用。
有两种不同的 指南,垂直和水平。两个水平指南是 top
和 bottom
,两个垂直指南是 start
和 end
。
ConstraintLayout { // Create guideline from the start of the parent at 10% the width of the Composable val startGuideline = createGuidelineFromStart(0.1f) // Create guideline from the end of the parent at 10% the width of the Composable val endGuideline = createGuidelineFromEnd(0.1f) // Create guideline from 16 dp from the top of the parent val topGuideline = createGuidelineFromTop(16.dp) // Create guideline from 16 dp from the bottom of the parent val bottomGuideline = createGuidelineFromBottom(16.dp) }
要创建指南,请使用 createGuidelineFrom*
和所需的指南类型。这将创建一个可在 Modifier.constrainAs()
块中使用的引用。
障碍
障碍 引用多个可组合项以基于指定侧面上最极端的部件创建虚拟指南。
要创建障碍,请使用 createTopBarrier()
(或:createBottomBarrier()
、createEndBarrier()
、createStartBarrier()
),并提供构成障碍的引用。
ConstraintLayout { val constraintSet = ConstraintSet { val button = createRefFor("button") val text = createRefFor("text") val topBarrier = createTopBarrier(button, text) } }
然后,障碍可以在 Modifier.constrainAs()
块中使用。
链
链在一个轴(水平或垂直)上提供组状行为。另一个轴可以独立约束。
要创建链,请使用 createVerticalChain
或 createHorizontalChain
ConstraintLayout { val constraintSet = ConstraintSet { val button = createRefFor("button") val text = createRefFor("text") val verticalChain = createVerticalChain(button, text, chainStyle = ChainStyle.Spread) val horizontalChain = createHorizontalChain(button, text) } }
然后,链可以在 Modifier.constrainAs()
块中使用。
链可以使用不同的 ChainStyles
进行配置,这些样式决定如何处理可组合项周围的空间,例如
ChainStyle.Spread
:空间均匀分布在所有可组合项中,包括第一个可组合项之前和最后一个可组合项之后的空间。ChainStyle.SpreadInside
:空间均匀分布在所有可组合项中,第一个可组合项之前和最后一个可组合项之后没有空间。ChainStyle.Packed
:空间分布在第一个和最后一个可组合项之前和之后,可组合项彼此紧密排列,中间没有空间。
了解更多
从 使用 ConstraintLayout
的 Compose 示例 中实际操作的 API 中了解有关 Compose 中 ConstraintLayout
的更多信息。
为您推荐
- 注意:当 JavaScript 关闭时显示链接文本
- Compose 中的焦点
- Jetpack Compose 的 Kotlin
- Compose 布局基础知识