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

Jetpack Compose MultiComboBox组件onExpandedChange异常求助

问题原因分析

你遇到的问题核心在于**ExposedDropdownMenuBox的onExpandedChange lambda无法捕获到currentlySelected的最新值**:

  • onExpandedChange是在组件首次组合时被创建并传递给ExposedDropdownMenuBox的,后续currentlySelected的变化(比如选择/取消选项)不会触发ExposedDropdownMenuBox的重组,因此该lambda一直使用初始化时捕获的currentlySelected初始值。
  • 而ExposedDropdownMenu的onDismissRequest会随着currentlySelected的变化(选项操作会触发组件重组)重新生成,所以能拿到最新的选中状态,这就是点击外部区域收起时功能正常的原因。

另外,你的selectedSummary基于父组件传入的selectedIds生成,无法实时反映用户的临时选择,属于体验上的小瑕疵。

修复方案
  1. 使用rememberUpdatedState包装currentlySelected,确保onExpandedChange始终能访问到最新的选中状态。
  2. 将selectedSummary的生成逻辑改为基于当前选中状态,让显示内容实时同步用户操作。
修改后的完整代码
data class ComboOption(
    override val text: String,
    val id: Int,
) : SelectableOption

interface SelectableOption {
    val text: String
}

@Composable
fun MultiComboBox(
    labelText: String,
    options: List<ComboOption>,
    onOptionsChosen: (Set<ComboOption>) -> Unit,
    modifier: Modifier = Modifier,
    selectedIds: Set<Int> = emptySet(),
) {
    var expanded by remember { mutableStateOf(false) }
    val isEnabled by rememberUpdatedState { options.isNotEmpty() } 
    var currentlySelected by remember(options, selectedIds) {
        mutableStateOf(options.filter { it.id in selectedIds }.toSet())
    }
    
    // 保存最新选中状态的引用,确保lambda能拿到最新值
    val latestSelected by rememberUpdatedState(currentlySelected)

    ExposedDropdownMenuBox(
        expanded = expanded,
        onExpandedChange = {
            if (isEnabled()) {
                expanded = !expanded
                if (!expanded) {
                    onOptionsChosen(latestSelected)
                }
            }
        },
        modifier = modifier,
    ) {
        // 基于当前选中状态生成显示文本,实时同步用户操作
        val selectedSummary = when (latestSelected.size) {
            0 -> ""
            1 -> latestSelected.first().text
            else -> "Wybrano ${latestSelected.size}"
        }
        TextField(
            enabled = isEnabled(),
            modifier = Modifier.menuAnchor(),
            readOnly = true,
            value = selectedSummary,
            onValueChange = {},
            label = { Text(text = labelText) },
            trailingIcon = {
                ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded)
            },
            colors = ExposedDropdownMenuDefaults.textFieldColors(),
        )
        ExposedDropdownMenu(
            expanded = expanded,
            onDismissRequest = {
                expanded = false
                onOptionsChosen(latestSelected)
            },
        ) {
            options.forEach { option ->
                DropdownMenuItem(
                    text = {
                        Row(verticalAlignment = Alignment.CenterVertically) {
                            Checkbox(
                                checked = option in latestSelected,
                                onCheckedChange = { newCheckedState ->
                                    currentlySelected = if (newCheckedState) {
                                        currentlySelected + option
                                    } else {
                                        currentlySelected - option
                                    }
                                },
                            )
                            Text(text = option.text)
                        }
                    },
                    onClick = {
                        currentlySelected = if (option in latestSelected) {
                            currentlySelected - option
                        } else {
                            currentlySelected + option
                        }
                    },
                    contentPadding = ExposedDropdownMenuDefaults.ItemContentPadding,
                )
            }
        }
    }
}
额外说明
  • rememberUpdatedState的作用是在组合中保存最新的变量引用,即使持有该引用的lambda没有被重新创建,也能访问到最新的值。
  • 把selectedSummary改为基于latestSelected后,用户选择选项时文本框会实时更新,无需等到收起下拉框,提升了交互体验。

内容的提问来源于stack exchange,提问作者KarolKVimn

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 05:36:00