Jetpack Compose中DropdownMenu内Switch关闭菜单后状态不保存问题求助
问题原因
你代码里的categoryCheckedState每次Composable重组时都会被重新初始化所有值为true——因为categories.forEach { categoryCheckedState[category] = true }直接写在Composable根作用域,而非remember的初始化逻辑里。每次DropdownMenu关闭触发重组时,这行代码都会执行,把所有分类的选中状态重置为true,导致之前的选择丢失。
修正方案
- 正确初始化状态:把状态初始化逻辑放在
remember的lambda中,确保只执行一次 - 移除冗余变量:删除未实际使用的
selectedCategories - 统一状态更新逻辑:合并DropdownMenuItem点击和Switch状态变化的处理逻辑,避免冲突
以下是修正后的完整代码:
@OptIn(ExperimentalFoundationApi::class) @Composable fun TaskPageLayout( contentPadding: PaddingValues = PaddingValues() ) { val categories = listOf( Category("Home"), Category("Work"), Category("Chores") ) val tasks = listOf( Task("Task 1", categories[0], "High", "Easy"), Task("Task 2", categories[1], "Medium", "Medium"), Task("Task 3", categories[2], "Low", "Hard"), Task("Task 4", categories[0], "High", "Easy") ) var expanded by remember { mutableStateOf(false) } // 仅在首次组合时初始化状态 val categoryCheckedState = remember { mutableStateMapOf<Category, Boolean>().apply { categories.forEach { category -> this[category] = true } } } Column( modifier = Modifier .fillMaxSize() .padding(contentPadding) ) { Row( modifier = Modifier .fillMaxWidth() .padding(16.dp), horizontalArrangement = Arrangement.SpaceAround ) { Box { ElevatedButton(onClick = { expanded = true }) { Text("Category") } DropdownMenu( expanded = expanded, onDismissRequest = { expanded = false } ) { categories.forEach { category -> DropdownMenuItem( text = { Text(category.name) }, trailingIcon = { Switch( modifier = Modifier .semantics { contentDescription = "Switch to choose which categories to view" }, checked = categoryCheckedState[category] ?: false, onCheckedChange = { isChecked -> categoryCheckedState[category] = isChecked } ) }, onClick = { categoryCheckedState[category] = !categoryCheckedState[category]!! } ) } } } ElevatedButton( onClick = { /* Handle button click */ } ) { Text("Priority") } ElevatedButton(onClick = { /* Handle button click */ }) { Text("Difficulty") } } LazyColumn( modifier = Modifier.weight(1f), contentPadding = PaddingValues(horizontal = 16.dp, vertical = 16.dp) ) { val groupedTasks = tasks.groupBy { it.category } categories.forEach { category -> if (categoryCheckedState[category] == true) { stickyHeader { Box( modifier = Modifier .fillMaxWidth() .background(Color.LightGray) .padding(8.dp) ) { Text( text = category.name, modifier = Modifier.padding(8.dp) ) } } items(groupedTasks[category] ?: emptyList()) { task -> Text(text = task.name, modifier = Modifier.padding(8.dp)) } } } } } } // 补充必要的数据类定义 data class Category(val name: String) data class Task(val name: String, val category: Category, val priority: String, val difficulty: String)
关键说明
- 状态持久化:通过
remember的lambda初始化mutableStateMap,确保只有首次创建Composable时才会设置初始选中状态,后续重组不会覆盖已有状态 - 逻辑一致性:MenuItem点击和Switch状态变化都统一修改
categoryCheckedState,避免状态不一致问题 - 代码简化:移除无用变量,让代码结构更清晰
内容的提问来源于stack exchange,提问作者Lizzie
相关产品推荐
相关产品推荐

