Jetpack Compose如何将单选选中项传递到指定Text字段显示
问题原因
你当前实现无法在外层Text显示选中主题的核心原因是状态作用域错误:selectedOption的状态定义在了SingleChoiceView组件内部,只能被弹窗组件自身访问,外层的ComposableSettingTheme组件既读不到这个值,也没法感知值的变化。另外你的SingleChoiceView代码里还存在变量引用错误,循环中用了未定义的text变量,会直接导致编译失败。
修复方案
用Compose的状态提升机制即可解决:把选中项的状态挪到需要读取、展示该值的组件层级(也就是ComposableSettingTheme里),再把状态值和更新回调逐层传给下层的弹窗、单选列表组件,实现跨组件状态共享。
具体修改步骤:
- 把
selectedOption状态从SingleChoiceView中移除,定义在ComposableSettingTheme内部 - 给
AlertSingleChoiceView、SingleChoiceView新增选中值、选中值更新回调两个入参,把状态从外层逐层传入 - 修复
SingleChoiceView循环中的变量错误,把不存在的text替换为循环遍历的themeOption变量
修正后核心代码
@Composable fun ComposableSettingTheme() { val singleDialog = remember { mutableStateOf(false) } // 状态提升到当前层,默认选中「系统默认」 val (selectedOption, onOptionSelected) = remember { mutableStateOf("System default") } Column(modifier = Modifier .fillMaxWidth() .clickable(onClick = { singleDialog.value = true })) { Text(text = "Theme") // 直接读取状态值显示 Text(text = selectedOption) if (singleDialog.value) { AlertSingleChoiceView( state = singleDialog, selectedOption = selectedOption, onOptionSelected = onOptionSelected ) } } } @Composable fun AlertSingleChoiceView( state: MutableState<Boolean>, selectedOption: String, onOptionSelected: (String) -> Unit ) { CommonDialog(title = "Theme", state = state) { SingleChoiceView( selectedOption = selectedOption, onOptionSelected = onOptionSelected ) } } @Composable fun SingleChoiceView( selectedOption: String, onOptionSelected: (String) -> Unit ) { val radioOptions = listOf("Day", "Night", "System default") Column(Modifier.fillMaxWidth()) { radioOptions.forEach { themeOption -> Row( Modifier .fillMaxWidth() .clickable(onClick = { onOptionSelected(themeOption) }) .selectable( selected = (themeOption == selectedOption), onClick = { onOptionSelected(themeOption) } ) .padding(vertical = 8.dp) ) { RadioButton( selected = (themeOption == selectedOption), onClick = { onOptionSelected(themeOption) } ) Text( text = themeOption, modifier = Modifier.padding(start = 8.dp) ) } } } }
交互扩展(可选)
如果需要实现「点击取消不保存选择、仅点击OK才生效」的标准弹窗交互,只需要在弹窗层加一个临时状态记录选择,点击确认时再同步给外层即可,修改AlertSingleChoiceView如下:
@Composable fun AlertSingleChoiceView( state: MutableState<Boolean>, selectedOption: String, onOptionSelected: (String) -> Unit ) { // 弹窗内临时选中状态,初始值和外层已保存的选中值一致 val tempSelected = remember(selectedOption) { mutableStateOf(selectedOption) } CommonDialog( title = "Theme", state = state, confirmButton = { TextButton(onClick = { // 点击OK才把临时选择同步到外层状态 onOptionSelected(tempSelected.value) state.value = false }) { Text("OK") } }, dismissButton = { TextButton(onClick = { state.value = false }) { Text("Cancel") } } ) { SingleChoiceView( selectedOption = tempSelected.value, onOptionSelected = { tempSelected.value = it } ) } }
对应的CommonDialog需要补充按钮参数支持,修改后如下:
@Composable fun CommonDialog( title: String?, state: MutableState<Boolean>, content: @Composable (() -> Unit)? = null, confirmButton: @Composable () -> Unit = { TextButton(onClick = { state.value = false }) { Text("OK") } }, dismissButton: @Composable () -> Unit = { TextButton(onClick = { state.value = false }) { Text("Cancel") } } ) { AlertDialog( onDismissRequest = { state.value = false }, title = title?.let { { Column(Modifier.fillMaxWidth()) { Text(text = title) } } }, text = content, confirmButton = confirmButton, dismissButton = dismissButton ) }
效果截图


内容的提问来源于stack exchange,提问作者wbk727
相关产品推荐
相关产品推荐

