在传统的xml中,约束布局使用还是比较方便的,在Compose中使用还有些不一样
核心
compose是声明式UI,使用约束布局的核心在于,如何为组件创建id,并对其进行关联约束
在官方文档中,提供了两种方式:
第一种
直接预定义引用或者说是别名,在组件创建的时候,使用Modifier为其指定在约束布局中的别名,并指定约束。
@Composable
fun ConstraintLayoutContent() {
ConstraintLayout {
// 创建布局中组件的别名
val (button, text) = createRefs()
Button(
onClick = { /* Do something */ },
// 使用Modifier为组件设置在约束布局中的别名,并指定约束
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)
}
)
}
}
第二种
-
指定为组件的id构建别名,并指定相互之间的约束关系。构建成为一个ConstraintSet
-
然后将ConstraintSet作为参数传入约束布局
-
在约束布局中的组件指定相应的id
@Composable
fun DecoupledConstraintLayout() {
BoxWithConstraints {
// 获取统一管理的ConstraintSet
val constraints = decoupledConstraints(margin = 16.dp) // Portrait constraints
// ConstraintSet作为参数传入约束布局
ConstraintLayout(constraints) {
Button(
onClick = { /* Do something */ },
modifier = Modifier.layoutId("button") // 需要指定id。以便在ConstraintSet中构建别名管理
) {
Text("Button")
}
Text("Text", Modifier.layoutId("text"))
}
}
}
// 构建统一管理的ConstraintSet
private fun decoupledConstraints(margin: Dp): ConstraintSet {
return ConstraintSet {
// 为指定的id构建在约束布局中的引用别名
val button = createRefFor("button")
val text = createRefFor("text")
constrain(button) {
top.linkTo(parent.top, margin = margin)
}
constrain(text) {
top.linkTo(button.bottom, margin)
}
}
}
填充满约束
遇到的情况是,页面纵向排列了top, content, bottom。在top和bottom高度固定的情况下,想要content高度充满中间可用高度,直接只设置上下的约束并不能实现想要的效果。
还需要设置中间部分的width或者height为Dimension.fillToConstraints
比如:
private fun setConstraintSet(): ConstraintSet {
return ConstraintSet {
val topBar = createRefFor("topBar")
val content = createRefFor("content")
val bottomBar = createRefFor("bottom")
constrain(topBar) {
top.linkTo(parent.top)
start.linkTo(parent.start)
}
constrain(content) {
top.linkTo(topBar.bottom)
start.linkTo(parent.start)
bottom.linkTo(bottomBar.top)
height = Dimension.fillToConstraints // 注意这里要设置一下
}
constrain(bottomBar) {
bottom.linkTo(parent.bottom)
start.linkTo(parent.start)
}
}
}