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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 22:56:02