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

Jetpack Compose横竖屏切换时,如何避免Row/Column切换导致状态丢失?

问题原因

屏幕方向变化时,when分支会切换渲染Row或Column组件,这会导致原来分支中的content节点被从Compose布局树中移除,新分支的content节点被重新创建,进而使得content内部用remember保存的状态因Composable节点销毁而丢失。

解决方案

方案1:给content添加固定Key

通过key函数为content标记统一的标识,让Compose识别不同分支中的content是同一个节点,从而保留其内部状态。

@Composable
fun ComponentsPage(
    modifier: Modifier = Modifier,
    content: @Composable (modifier: Modifier) -> Unit,
) {
    val configuration = LocalConfiguration.current

    when (configuration.orientation) {
        Configuration.ORIENTATION_LANDSCAPE -> {
            Row(modifier.fillMaxSize()) {
                key("stable-content-node") {
                    content(Modifier.weight(1f).fillMaxHeight())
                }
            }
        }
        else -> {
            Column(modifier.fillMaxSize()) {
                key("stable-content-node") {
                    content(Modifier.weight(1f).fillMaxWidth())
                }
            }
        }
    }
}

方案2:用rememberSaveable替代remember

如果无法保证content节点的稳定性,可将内部状态改用rememberSaveable存储,它会把状态持久化到Bundle中,即使Composable被销毁重建也能恢复状态。

// 在content内部替换原有remember代码
var enteredPassword by rememberSaveable { mutableStateOf("") }

方案3:自定义统一布局容器

通过自定义Layout组件,根据屏幕方向动态调整布局逻辑,让content始终作为同一个容器的子节点,避免分支切换导致的节点销毁。

@Composable
fun OrientationLayout(
    modifier: Modifier = Modifier,
    content: @Composable (modifier: Modifier) -> Unit,
) {
    val configuration = LocalConfiguration.current
    val isLandscape = configuration.orientation == Configuration.ORIENTATION_LANDSCAPE

    Layout(
        modifier = modifier.fillMaxSize(),
        content = { content(Modifier.weight(1f)) }
    ) { measurables, constraints ->
        // 根据方向调整测量约束
        val contentConstraints = if (isLandscape) {
            constraints.copy(minWidth = constraints.maxWidth)
        } else {
            constraints.copy(minHeight = constraints.maxHeight)
        }
        val placeable = measurables.first().measure(contentConstraints)

        // 执行布局
        layout(constraints.maxWidth, constraints.maxHeight) {
            placeable.placeRelative(0, 0)
        }
    }
}

// 使用示例
OrientationLayout { modifier ->
    // 这里放置你的内容组件
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 18:25:59