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

Jetpack Compose中如何根据一个exposed dropdown menu值过滤另一菜单选项

Jetpack Compose 级联Exposed Dropdown Menu实现方案

完全可以实现该需求,核心逻辑是通过Compose的状态托管机制,监听第一个下拉菜单的选中值,动态计算第二个下拉菜单的可选数据源即可,以下是品牌-车型级联选择的具体实现:

实现核心逻辑

  • 提前维护品牌与对应车型的映射关系数据
  • 通过remember托管下拉菜单展开状态、选中品牌、选中车型三类状态
  • 监听品牌选中事件,品牌变更时自动重置已选车型,同步更新车型下拉的可选列表
  • 未选中品牌时可将车型下拉置为禁用状态,避免无效操作

完整实现代码

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExposedDropdownMenuBox
import androidx.compose.material3.ExposedDropdownMenuDefaults
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

// 定义品牌-车型数据结构
data class CarBrand(
    val name: String,
    val models: List<String>
)

// 预置品牌与对应车型数据
val localCarBrandList = listOf(
    CarBrand("比亚迪", listOf("汉EV", "唐DM-i", "海豹", "元PLUS")),
    CarBrand("特斯拉", listOf("Model 3", "Model Y", "Model S", "Model X")),
    CarBrand("丰田", listOf("凯美瑞", "卡罗拉", "汉兰达", "RAV4荣放"))
)

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun CascadingCarSelector() {
    // 品牌菜单展开状态
    var brandMenuExpanded by remember { mutableStateOf(false) }
    // 车型菜单展开状态
    var modelMenuExpanded by remember { mutableStateOf(false) }
    // 当前选中的品牌
    var currentSelectedBrand by remember { mutableStateOf<CarBrand?>(null) }
    // 当前选中的车型
    var currentSelectedModel by remember { mutableStateOf("") }

    Column(
        modifier = Modifier
            .padding(16.dp)
            .fillMaxWidth(),
        verticalArrangement = Arrangement.spacedBy(16.dp)
    ) {
        // 品牌选择下拉框
        ExposedDropdownMenuBox(
            expanded = brandMenuExpanded,
            onExpandedChange = { brandMenuExpanded = !brandMenuExpanded }
        ) {
            TextField(
                value = currentSelectedBrand?.name ?: "请选择汽车品牌",
                onValueChange = {},
                readOnly = true,
                trailingIcon = {
                    ExposedDropdownMenuDefaults.TrailingIcon(expanded = brandMenuExpanded)
                },
                modifier = Modifier
                    .menuAnchor()
                    .fillMaxWidth()
            )
            ExposedDropdownMenu(
                expanded = brandMenuExpanded,
                onDismissRequest = { brandMenuExpanded = false }
            ) {
                localCarBrandList.forEach { brand ->
                    DropdownMenuItem(
                        text = { Text(text = brand.name) },
                        onClick = {
                            currentSelectedBrand = brand
                            // 切换品牌时重置已选车型,避免数据不匹配
                            currentSelectedModel = ""
                            brandMenuExpanded = false
                        }
                    )
                }
            }
        }

        // 车型选择下拉框
        ExposedDropdownMenuBox(
            expanded = modelMenuExpanded,
            onExpandedChange = {
                // 未选择品牌时不允许展开车型菜单
                if (currentSelectedBrand != null) {
                    modelMenuExpanded = !modelMenuExpanded
                }
            }
        ) {
            TextField(
                value = currentSelectedModel.ifEmpty { "请选择对应车型" },
                onValueChange = {},
                readOnly = true,
                enabled = currentSelectedBrand != null,
                trailingIcon = {
                    ExposedDropdownMenuDefaults.TrailingIcon(expanded = modelMenuExpanded)
                },
                modifier = Modifier
                    .menuAnchor()
                    .fillMaxWidth()
            )
            ExposedDropdownMenu(
                expanded = modelMenuExpanded,
                onDismissRequest = { modelMenuExpanded = false }
            ) {
                // 直接渲染当前选中品牌对应的车型列表
                currentSelectedBrand?.models?.forEach { model ->
                    DropdownMenuItem(
                        text = { Text(text = model) },
                        onClick = {
                            currentSelectedModel = model
                            modelMenuExpanded = false
                        }
                    )
                }
            }
        }
    }
}

注意事项:切换品牌时必须清空之前选中的车型值,否则会出现选中车型不属于当前品牌的逻辑错误;如果车型数据需要从接口拉取,可以在品牌选中的回调里触发网络请求,将返回的车型列表赋值给状态即可,逻辑和本地数据过滤完全一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 15:45:49