跳转至

ConstraintLayout

ConstraintLayout 可以让组件相对屏幕或其他同级组件进行布局,可以减少 Row、Column、Box 布局的互相嵌套。

想要在项目中使用ConstraintLayout,必须在 app/build.gradle 中增加信赖

implementation "androidx.constraintlayout:constraintlayout-compose:1.0.0-beta02"

用法

  • 通过 createRefs 或 createRefFor 创建引用,每一个组件需要有一个引用
  • 通过 Modifier.constrainAs 关联引用
  • 在 constrainAs 的 body 块中使用 linkTo 、centerVerticallyTo等设置约束
  • parent 是默认的父组件的引用,可以直接使用
@Composable
fun ConstraintLayoutSample() {

    var isChecked by remember {
        mutableStateOf(false)
    }

    ConstraintLayout(
        modifier = Modifier
            .height(100.dp)
            .fillMaxWidth()
            .background(Color.Yellow)
    ) {
        val (icon, primaryText, secondlyText, checkBox) = createRefs()

        Icon(
            imageVector = Icons.Default.AccountBox,
            contentDescription = null,
            modifier = Modifier.constrainAs(icon) {
                top.linkTo(parent.top)
                start.linkTo(parent.start, margin = 8.dp)
                bottom.linkTo(parent.bottom)
            })

        Text(
            "Primary Text",
            fontSize = 25.sp,
            fontWeight = FontWeight.Bold,
            modifier = Modifier.constrainAs(primaryText) {
                start.linkTo(icon.end, margin = 8.dp)
                top.linkTo(parent.top)
            })

        Text("secondly text", modifier = Modifier.constrainAs(secondlyText) {
            start.linkTo(primaryText.start)
            top.linkTo(primaryText.top)
            bottom.linkTo(parent.bottom)
        })

        Checkbox(
            checked = isChecked,
            onCheckedChange = { isChecked = it },
            modifier = Modifier.constrainAs(checkBox) {
                centerVerticallyTo(parent)
                end.linkTo(parent.end)
            })
    }
}

ConstraintsLayout1

解耦

在上面的例子中,我们可以看到约束直接写到组件代码之中,这样不容易让这个约束重复利用,因此我们把这些约束代码解耦出来。

所以我们可以使用另一种方案来实现

  • 给 ConstraintsLayout 设置 ContraintSet
  • 通过设置 layoutId 来关联组件
@Composable
fun ConstraintLayoutSample1() {
    var isChecked by remember {
        mutableStateOf(false)
    }

    LazyColumn() {
        item {
            ConstraintLayout(
                modifier = Modifier
                    .height(100.dp)
                    .fillMaxWidth()
                    .background(Color.Yellow), 
                constraintSet = decoupledConstraints()
            ) {

                Icon(
                    imageVector = Icons.Default.AccountBox,
                    contentDescription = null,
                    modifier = Modifier.layoutId("icon")
                )

                Text(
                    "Primary Text",
                    fontSize = 25.sp,
                    fontWeight = FontWeight.Bold,
                    modifier = Modifier.layoutId("primaryText")
                )

                Text("secondly text",
                    modifier = Modifier.layoutId("secondlyText"))

                Checkbox(
                    checked = isChecked,
                    onCheckedChange = { isChecked = it },
                    modifier = Modifier.layoutId("checkBox")
                )
            }
        }
    }
}

private fun decoupledConstraints(): ConstraintSet {
  return ConstraintSet {
        val icon = createRefFor("icon")
        val primaryText = createRefFor("primaryText")
        val secondlyText = createRefFor("secondlyText")
        val checkBox = createRefFor("checkBox")

        constrain(icon) {
            centerVerticallyTo(parent)
            start.linkTo(parent.start, margin = 8.dp)
        }

        constrain(primaryText) {
            start.linkTo(icon.end, margin = 8.dp)
            top.linkTo(parent.top)
        }

        constrain(secondlyText) {
            start.linkTo(primaryText.start)
            bottom.linkTo(parent.bottom)
            top.linkTo(primaryText.bottom)
        }

        constrain(checkBox) {
            centerVerticallyTo(parent)
            end.linkTo(parent.end)
        }
    }
}

这样,如果想重复使用这一组约束,就变得很简单了

视频教程