Jetpack Compose中如何封装可复用的对话框组件
Dialog组件复用实现方案
核心逻辑是把弹窗中固定不变的结构、通用交互封装成独立组件,把随列表项变化的内容(标题、跳转路由)通过参数传入,同时页面只挂载一次弹窗,用状态持有当前选中的列表项,避免为每个条目重复写弹窗代码。
第一步:补全枚举配置,统一管理列表项参数
把每个列表项对应的资源、跳转路由直接绑定在枚举中,后续新增条目只需要改枚举,不需要写额外的分支判断:
enum class Items( @StringRes val textResId: Int, val navRoute: String ) { Starters(R.string.starters, Screen.Starters.route), // 按你需求,Desserts暂时也跳Starters路由,后续要修改直接改这里即可 Desserts(R.string.desserts, Screen.Starters.route) }
第二步:抽离通用可复用弹窗组件
把弹窗的固定结构、默认文案、通用交互(比如确认后自动关闭弹窗)封装在组件内部,可变内容暴露为入参:
@Composable fun OrderConfirmDialog( title: String, onDismiss: () -> Unit, onConfirm: () -> Unit, contentText: String = "Ready to order?", confirmText: String = "Order food", dismissText: String = "Cancel" ) { AlertDialog( onDismissRequest = onDismiss, title = { Text(title) }, text = { Text(contentText) }, confirmButton = { Button(onClick = { onConfirm() onDismiss() }) { Text(confirmText) } }, dismissButton = { OutlinedButton(onClick = onDismiss) { Text(dismissText) } } ) }
第三步:改造页面状态逻辑
只需要一个状态持有当前选中的列表项,弹窗仅在页面顶层挂载一次,根据选中项动态传参,不需要为每个列表项写独立的弹窗触发逻辑:
@Composable fun MainScreen(navController: NavController) { // 用可空类型存储选中项,值为null时弹窗关闭 val currentSelectedItem = remember { mutableStateOf<Items?>(null) } // 弹窗挂载在组合树顶层,仅当有选中项时显示 currentSelectedItem.value?.let { selected -> OrderConfirmDialog( title = stringResource(id = selected.textResId), onDismiss = { currentSelectedItem.value = null }, onConfirm = { navController.navigate(selected.navRoute) } ) } // 列表点击逻辑极简,点哪个就把选中项设为哪个,自动触发弹窗 val onItemClick: (Items) -> Unit = { clicked -> currentSelectedItem.value = clicked } Scaffold( topBar = { /* 原有顶部栏逻辑 */ }, content = { paddingValues -> LazyColumn( modifier = Modifier.padding(paddingValues) ) { items(Items.entries.toList()) { item -> // 可直接替换为你原有的自定义列表项组件 Text( text = stringResource(id = item.textResId), modifier = Modifier .fillMaxWidth() .clickable { onItemClick(item) } .padding(16.dp) ) } } }, containerColor = MaterialTheme.colorScheme.background // 替换成你需要的颜色值 ) }
避坑说明
不要在点击回调的when分支里直接调用MyDialog组件:Composable组件必须在组合树中挂载才能正常渲染,在事件回调里直接调用Composable会导致渲染异常、状态丢失,正确做法是把弹窗放在组合上下文里,用状态控制显示隐藏。
这个方案后续新增列表项时,只需要在Items枚举里加对应条目、绑定字符串资源和路由即可,不需要修改弹窗代码、不需要新增判断分支,完全消除重复代码。
内容的提问来源于stack exchange,提问作者wbk727
相关产品推荐
相关产品推荐

