You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SubcomposeLayout移除可放置项异常:关闭后bottom组件仍在组件树

问题原因

你当前的代码中,无论expanded状态是true还是false,都会执行subcompose(ExpandedItemSlot.BOTTOM, bottom)——这一步已经完成了bottom对应Composable的组合(composition)流程,所以哪怕你不在layout块中放置它,它依然会存在于组件树里,只是处于「未放置」状态,布局检查器会正常显示它。

解决方案

要真正移除bottom组件,核心是仅在expanded为true时才对bottom执行subcompose操作,修改后的代码如下:

@Composable
fun ExpandItem(
    top: @Composable () -> Unit,
    bottom: @Composable () -> Unit,
    expanded: Boolean,
    modifier: Modifier = Modifier,
) {
    SubcomposeLayout(modifier = modifier) { constraints ->
        val topPlaceable = subcompose(ExpandedItemSlot.TOP, top).map { measurable ->
            measurable.measure(constraints)
        }.first()

        // 仅在展开状态下才组合bottom内容
        val bottomPlaceable = if (expanded) {
            subcompose(ExpandedItemSlot.BOTTOM, bottom).map { measurable ->
                measurable.measure(constraints)
            }.first()
        } else {
            null
        }

        val width = maxOf(
            topPlaceable.width,
            bottomPlaceable?.width ?: topPlaceable.width
        )
        val height = if(expanded) {
            topPlaceable.height + (bottomPlaceable?.height ?: 0)
        } else {
            topPlaceable.height
        }

        layout(width, height) {
            topPlaceable.placeRelative(0, 0)
            bottomPlaceable?.let {
                it.placeRelative(0, topPlaceable.height)
            }
        }
    }
}

private enum class ExpandedItemSlot {
    TOP, BOTTOM
}

补充说明

SubcomposeLayout的subcompose方法是触发Composable组合的关键:只要调用该方法,对应的内容就会进入组合流程,这和后续是否执行placeRelative(布局阶段操作)无关。组件树的存在与否,取决于组合阶段是否执行,而非布局阶段是否放置。

内容的提问来源于stack exchange,提问作者Fillipe Duoli

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 21:36:28