当子组件大小发生变化时,如何调整组件的大小以适应其子组件并保持不变?(Jetpack 撰写)

And*_*zPL 3 android kotlin android-jetpack-compose

我有一个 Compose 组件,里面有一个盒子和 2 个组件,但它们永远不会同时可见。我想将此框的大小调整为第一个组件,并在该组件不可见时保持不变。

Box(
    modifier = modifier.then(Modifier.background(bgColor)),
    contentAlignment = Alignment.Center
) {
    if (componentVisible1) {
        Button(
            modifier = Modifier.height(48.dp).widthIn(144.dp),
            onClick = onClicked,
            enabled = enabled
        ) {
            Text(
                text = "text1",
            )
        }
    }

    if (component2Visible) {
        CircularProgressIndicator(
            modifier = Modifier.size(24.dp).background(buttonColor, CircleShape).padding(2.dp),
            strokeWidth = 2.dp
        )
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,当 component1 不可见时,框的宽度会减小。

Thr*_*ian 5

如果另一个可组合项依赖于它而无需重新组合,或者在您的情况下,即使它甚至不在组合中,您可以使用SubcomposeLayout来传递可组合项的维度。

@Composable
internal fun DimensionSubcomposeLayout(
    modifier: Modifier = Modifier,
    mainContent: @Composable () -> Unit,
    dependentContent: @Composable (DpSize) -> Unit
) {

    val density = LocalDensity.current
    SubcomposeLayout(
        modifier = modifier
    ) { constraints: Constraints ->

        // Subcompose(compose only a section) main content and get Placeable
        val mainPlaceable: Placeable = subcompose(SlotsEnum.Main, mainContent)
            .map {
                it.measure(constraints.copy(minWidth = 0, minHeight = 0))
            }.first()


        val dependentPlaceable: Placeable =
            subcompose(SlotsEnum.Dependent) {
                dependentContent(
                    DpSize(
                        density.run { mainPlaceable.width.toDp() },
                        density.run { mainPlaceable.height.toDp() }
                    )
                )
            }
                .map { measurable: Measurable ->
                    measurable.measure(constraints)
                }.first()


        layout(mainPlaceable.width, mainPlaceable.height) {
            dependentPlaceable.placeRelative(0, 0)
        }
    }
}

/**
 * Enum class for SubcomposeLayouts with main and dependent Composables
 */
enum class SlotsEnum { Main, Dependent }
Run Code Online (Sandbox Code Playgroud)

您可以使用它根据测量或组合按钮来设置盒子的尺寸。

@Composable
private fun DimensionSample() {

    var componentVisible1 by remember { mutableStateOf(false) }
    var component2Visible by remember { mutableStateOf(true) }
    Column {

        Button(onClick = {
            componentVisible1 = !componentVisible1
            component2Visible = !component2Visible
        }) {
            Text(text = "Toggle")
        }

        val button = @Composable {
            Button(
                modifier = Modifier
                    .height(48.dp)
                    .widthIn(144.dp),
                onClick = {}

            ) {
                Text(
                    text = "text1",
                )
            }
        }

        val circularProgressIndicator = @Composable {
            CircularProgressIndicator(
                modifier = Modifier
                    .size(24.dp)
                    .background(Color.Yellow, CircleShape)
                    .padding(2.dp),
                strokeWidth = 2.dp
            )
        }




        DimensionSubcomposeLayout(mainContent = {
            button()
        }) {
            Box(
                modifier = Modifier
                    .size(it)
                    .then(Modifier.background(Color.Red)),
                contentAlignment = Alignment.Center
            ) {
                if (componentVisible1) {
                    button()
                }

                if (component2Visible) {
                    circularProgressIndicator()
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述