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

Jetpack Compose中ModalBottomSheet如何向上一页面回传值

Jetpack Compose ModalBottomSheet 收起并回传数据实现方案

核心逻辑靠Compose的状态提升机制实现,不要在弹窗内部私藏状态,把弹窗显示控制、数据接收的状态都放在弹窗的父页面(也就是唤起弹窗的上一级页面)持有即可。

具体实现步骤

  • 父页面统一管理核心实例:协程作用域(用来调用挂起的弹窗收起方法)、底部弹窗状态对象、弹窗显示标记位、回传数据的接收状态
  • 弹窗内部按钮点击时按顺序执行逻辑:先挂起等待弹窗完全收起动画执行完成,再把待传递的数据赋值给父页面的状态,最后更新弹窗显示标记位移除弹窗组合
  • 禁止提前把弹窗显示标记位置为false,否则弹窗会被直接从视图树移除,既会打断收起动画,还会触发ModalBottomSheet的状态访问异常

完整可运行代码示例

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun UpperLevelPage() {
    // 父页面持有的所有状态,不放在弹窗内部
    val coroutineScope = rememberCoroutineScope()
    val bottomSheetState = rememberModalBottomSheetState()
    var showBottomSheet by remember { mutableStateOf(false) }
    // 替换成你自己的业务数据类型即可,自定义数据类、基本类型都支持
    var backDataFromSheet by remember { mutableStateOf("初始无数据") }

    Scaffold { innerPadding ->
        Column(
            modifier = Modifier
                .fillMaxSize()
                .padding(innerPadding),
            verticalArrangement = Arrangement.Center,
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            Text(text = "接收到的弹窗回传内容:$backDataFromSheet")
            Spacer(modifier = Modifier.height(20.dp))
            Button(onClick = { showBottomSheet = true }) {
                Text(text = "唤起底部弹窗")
            }
        }

        // 控制弹窗渲染
        if (showBottomSheet) {
            ModalBottomSheet(
                onDismissRequest = { showBottomSheet = false },
                sheetState = bottomSheetState
            ) {
                Column(
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(horizontal = 16.dp, vertical = 24.dp),
                    horizontalAlignment = Alignment.CenterHorizontally
                ) {
                    // 你要回传的业务数据
                    val targetData = "弹窗操作生成的业务数据"
                    Button(onClick = {
                        coroutineScope.launch {
                            // 第一步:等待弹窗收起动画完全执行完成
                            bottomSheetState.hide()
                            // 第二步:给父页面状态赋值,完成数据传递
                            backDataFromSheet = targetData
                            // 第三步:标记弹窗隐藏,从组合中移除弹窗
                            showBottomSheet = false
                        }
                    }) {
                        Text(text = "收起弹窗并回传数据")
                    }
                }
            }
        }
    }
}

复杂场景适配

如果页面层级较深,不想逐层传递回调,可以把状态抽成共享ViewModel:父页面和弹窗从同一个导航栈条目获取ViewModel实例,弹窗内部直接修改ViewModel中暴露的可观察状态,父页面对该状态做观察即可,本质还是状态上提的思路,只是状态存放位置移到了ViewModel。

注意:不要尝试用路由框架的返回栈传参、或者全局EventBus实现这个逻辑,会破坏生命周期一致性,极易产生内存泄漏和状态不一致问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 16:18:20