Android记录--Compose中,约束布局的使用小记

14 阅读2分钟

在传统的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)
            }
        )
    }
}

第二种

  1. 指定为组件的id构建别名,并指定相互之间的约束关系。构建成为一个ConstraintSet

  2. 然后将ConstraintSet作为参数传入约束布局

  3. 在约束布局中的组件指定相应的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)
        }
    }
}