与基于视图的ConstraintLayout相比,Compose ConstraintLayout是否为INVISIBLE和GONE提供相同的处理?

问题描述

免责声明:我知道Compose刚刚输入了alpha01,因此我不希望所有功能都可以 可用。但是,恕我直言,特定布局案例的布局和处理是一个重要主题 应该早点解决。

当前基于视图的 ConstraintLayout提供了一些特定的处理方式,以防出现子视图 标记为GONE,请参阅 ConstrainLayout documentation

我检查了撰写 ConstraintLayout文档,可用的修饰符等,但是 没有找到任何指向这个方向的东西。我也找不到任何有关的提示 INVISIBLE以及撰写 ConstraintLayout的处理方式/方式,例如基于视图的 ConstraintLayout

通常,当前基于视图的布局(例如LinearLayout)在一个广告素材中处理INVISIBLEGONE 类似的方式:

  • 如果视图处于状态INVISIBLE,则该视图是其大小的布局的一部分,只是没有 如图所示。其他视图的整体布局不会发生变化,而是保持在原位置。

  • 如果视图处于状态GONE,则通常将其大小视为0,并重新计算布局,然后 更改,其他视图通常会更改其位置。

这里有一个简单的Compose ConstraintLayout UI,连续只有4个按钮,链接起来很漂亮 传播。

// if dontShow is 0 then show all buttons,otherwise make the button with this number
// somehow INVISIBLE. This feature is not yet implemented.
@Composable
fun fourButtonsCL(dontShow: Int) {
    ConstraintLayout(Modifier.fillMaxSize()) {
        val (btn1,btn2,btn3,btn4) = createRefs()
        TextButton(onClick = {},Modifier.constrainAs(btn1) {}.background(teal200)) { Text("Button1") }
        TextButton(onClick = {},Modifier.constrainAs(btn2) {}.background(teal200)) { Text("Button2") }
        TextButton(onClick = {},Modifier.constrainAs(btn3) {}.background(teal200)) { Text("Button3") }
        TextButton(onClick = {},Modifier.constrainAs(btn4) {}.background(teal200)) { Text("Button4") }

        createHorizontalChain(btn1,btn4)
    }
}

@Preview(showBackground = true)
@Composable
fun previewThreeButtons() {
    ComposeAppTheme {
        fourButtonsCL()
    }
}

假设我想使Button3不可见,但将其他3个按钮保持在它们所处的位置 是。因此,Button2Button4之间只是一个空洞。如何在不创造另一个的情况下实现这一目标 可组合或添加其他逻辑。虽然在这种简单情况下的逻辑可能只是一个观点 对于代码,更复杂的布局将需要一些更复杂的逻辑。基于veConw的ConstraintLayout 我们只需要修改子视图。

另一个假设:使Button3从布局(GONE)中完全消失,然后重新计算 布局,其余按钮变得更宽且均匀分布。乍一看,这看起来很简单, 在这个非常简单的示例中,这可能很容易。但是,在更复杂的布局中,这可能需要 对嵌入式Composables的约束进行了部分甚至很多重新布线。

因此,问题是: 对于ColumnRow布局,compose如何处理这些情况(例如在基于视图的LinearLayout中) 特别是ConstraintLayout?但是有以下限制?:未定义 许多新的Composables和/或未在Composables内部添加复杂的布局逻辑(重新布线) 约束)。

我错过了一些修饰符吗?这在可组合布局中是否有计划甚至可行?会是什么 解决Compose中此类布局问题的首选方法?

解决方法

基于@CommonsWare对我可以解决INVISIBLE的问题的评论 选项,请参见下面的代码。

当前(在alpha-01中),ConstraintLayout的实现似乎不完整,代码中至少有几个 TODO 注释表明了这一点。这个 似乎包括GONE功能尚未提供的支持。 我看到了其中一些:

// TODO(popam,b / 158069248):添加用于消失边距的参数

此外,链功能还无法以与 在基于视图的ConstraintLayout中。

object FourElementsNoDSL {
    const val elementA = "ElementA"
    const val elementB = "ElementB"
    const val elementC = "ElementC"
    const val elementD = "ElementD"

    private val noDSLConstraintSet = ConstraintSet {

        // Create references with defines ids,here using a string as id. Could be an Int as well,// actually it's defined as 'Any'
        val elemA = createRefFor(elementA)
        val elemB = createRefFor(elementB)
        val elemC = createRefFor(elementC)
        val elemD = createRefFor(elementD)

        // Simple chain only. Instead of this simple chain we can use (for example):
        //     constrain(elemA) {start.linkTo(parent.start) }
        // to set a constraint as known in XML

//        constrain(elemA) {start.linkTo(parent.start,16.dp) }
//        constrain(elemB) {start.linkTo(elemA.end) }
//        constrain(elemC) {start.linkTo(elemB.end) }
//        constrain(elemD) {end.linkTo(parent.end) }
        createHorizontalChain(elemA,elemB,elemC,elemD)
    }

    @Composable
    fun fourButtonsCLNoDSL(doNotShow: List<String>) {
        ConstraintLayout(constraintSet = noDSLConstraintSet,modifier = Modifier.fillMaxSize()) {

            // This block contains the children
            Text(text = "A",modifier = Modifier.layoutId(elementA)
                            .drawOpacity(if (doNotShow.contains(elementA)) 0f else 1f)
                            .padding(0.dp),style = TextStyle(fontSize = 20.sp)
            )
            Text(text = "B",modifier = Modifier.layoutId(elementB)
                            .drawOpacity(if (doNotShow.contains(elementB)) 0f else 1f)
                            .padding(0.dp),style = TextStyle(fontSize = 20.sp)
            )
            Text(text = "C",modifier = Modifier.layoutId(elementC)
                            .drawOpacity(if (doNotShow.contains(elementC)) 0f else 1f)
                            .padding(0.dp),style = TextStyle(fontSize = 20.sp)
            )
            Text(text = "D",modifier = Modifier.layoutId(elementD)
                            .drawOpacity(if (doNotShow.contains(elementD)) 0f else 1f)
                            .padding(0.dp),style = TextStyle(fontSize = 20.sp))

        }
    }
}

@Preview(showBackground = true)
@Composable
fun previewFourFieldsNoDSL() {
    val noShow = listOf(FourElementsNoDSL.elementC)
    PlaygroundTheme {
        FourElementsNoDSL.fourButtonsCLNoDSL(noShow)
    }
}

object FourElementsNoDSL定义了布局,提供了元素ID等。 这与包含这种布局的XML文件大致相当。 noDSL 表示此布局不使用Compose ConstraintLayout的Kotlin DSL。当前,DSL不提供设置元素引用的机制 (在layoutId中使用),其ID已在本示例中完成。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...