Kotlin中如何在循环中为每个下拉列表创建独立变量?
解决循环复用下拉列表同步变化的问题
问题原因
你当前的代码中,所有循环生成的下拉列表共用同一个songVar选中值状态和expanded展开状态变量,因此修改任意一个下拉框时,所有组件都会读取同一个状态值,导致同步变化。
解决方案
将每个下拉列表封装为独立的Composable组件,让每个组件内部维护自己的状态变量,确保实例间状态互不干扰。如果需要在父组件中统一管理所有选中值,可通过回调传递数据。
方案1:封装独立组件并统一管理选中值
先定义单个下拉列表的Composable:
@Composable fun SingleExposedDropdownMenu( label: String, options: List<String>, initialValue: String = "", onValueSelected: (String) -> Unit ) { // 每个组件独立维护展开状态和选中值 var expanded by rememberSaveable { mutableStateOf(false) } var selectedValue by rememberSaveable { mutableStateOf(initialValue) } ExposedDropdownMenuBox( expanded = expanded, onExpandedChange = { expanded = !expanded }, modifier = Modifier .padding(vertical = 8.dp) .width(200.dp) ) { CompositionLocalProvider(LocalTextInputService provides null) { TextField( readOnly = true, value = selectedValue, onValueChange = {}, // 只读状态无需处理输入 label = { Text(label) }, trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) }, colors = ExposedDropdownMenuDefaults.textFieldColors(), modifier = Modifier.menuAnchor() ) } ExposedDropdownMenu( expanded = expanded, onDismissRequest = { expanded = false } ) { options.forEach { option -> DropdownMenuItem( text = { Text(option) }, onClick = { selectedValue = option onValueSelected(option) // 将选中值传递给父组件 expanded = false }, contentPadding = ExposedDropdownMenuDefaults.ItemContentPadding ) } } } }
然后在父组件中循环创建20个实例,并通过列表存储所有选中值:
@Composable fun MultipleDropdownsScreen() { val options = rememberSaveable { listOf("选项1", "选项2", "选项3") // 替换为你的实际选项列表 } // 初始化20个空字符串,对应每个下拉框的初始选中值 val selectedSongs = rememberSaveable { mutableStateListOf<String>().apply { repeat(20) { add("") } } } Column(Modifier.padding(horizontal = 8.dp)) { for (i in 0 until 20) { SingleExposedDropdownMenu( label = "Song${i+1}:", options = options, initialValue = selectedSongs[i], onValueSelected = { selectedValue -> selectedSongs[i] = selectedValue // 这里可以添加选中后的逻辑,比如保存到本地或提交数据 } ) } } }
方案2:独立组件自行维护状态(无需父组件管理)
如果不需要在父组件中统一管理选中值,可简化组件,让每个下拉框自己维护状态:
@Composable fun SingleExposedDropdownMenu( label: String, options: List<String>, initialValue: String = "" ) { var expanded by rememberSaveable { mutableStateOf(false) } var selectedValue by rememberSaveable { mutableStateOf(initialValue) } ExposedDropdownMenuBox( expanded = expanded, onExpandedChange = { expanded = !expanded }, modifier = Modifier .padding(vertical = 8.dp) .width(200.dp) ) { CompositionLocalProvider(LocalTextInputService provides null) { TextField( readOnly = true, value = selectedValue, onValueChange = {}, label = { Text(label) }, trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) }, colors = ExposedDropdownMenuDefaults.textFieldColors(), modifier = Modifier.menuAnchor() ) } ExposedDropdownMenu( expanded = expanded, onDismissRequest = { expanded = false } ) { options.forEach { option -> DropdownMenuItem( text = { Text(option) }, onClick = { selectedValue = option expanded = false }, contentPadding = ExposedDropdownMenuDefaults.ItemContentPadding ) } } } }
父组件直接循环调用即可:
@Composable fun MultipleDropdownsScreen() { val options = rememberSaveable { listOf("选项1", "选项2", "选项3") } Column(Modifier.padding(horizontal = 8.dp)) { for (i in 1..20) { SingleExposedDropdownMenu( label = "Song$i:", options = options ) } } }
内容的提问来源于stack exchange,提问作者The Quackiest
相关产品推荐
相关产品推荐

