Compose Multiplatform Android端ExposedDropdownMenu选项无法点击问题求助
问题现象
桌面端下拉菜单运行正常;Android端(模拟器及多款真机测试)可展开ExposedDropdownMenu查看选项,但无法点击/选中选项,仅能正常收起菜单。
临时可用的替代操作:
- 为Android设备连接键盘,通过方向键导航至目标选项后按回车选中;
- 点击按钮跳转至其他页面,再返回包含下拉菜单的原页面。
相关环境信息
- 使用Voyager进行页面导航;
- 所有依赖已更新至最新版本。
下拉菜单实现代码
@OptIn(ExperimentalMaterialApi::class) @Composable fun CustomExposedDropDown( label: @Composable BoxScope.() -> Unit, items: List<@Composable RowScope.() -> Unit>, onChange: (Int) -> Unit, modifier: Modifier = Modifier ) { var isExpanded by remember { mutableStateOf(false) } val iconRotation by animateFloatAsState(if (isExpanded) 180f else 0f) ExposedDropdownMenuBox( expanded = isExpanded, modifier = modifier, onExpandedChange = { isExpanded = it } ) { Box( contentAlignment = Alignment.Center, modifier = Modifier .fillMaxWidth() .heightIn(min = 36.dp) .background( color = MaterialTheme.colors.onSurface .copy(alpha = TextFieldDefaults.BackgroundOpacity), shape = RoundedCornerShape(10.dp) ) .clickable(onClick = {}) ) { label() Icon( imageVector = Icons.Filled.ArrowDropDown, contentDescription = "Dropdown", tint = MaterialTheme.colors.primary, modifier = Modifier .align(Alignment.CenterEnd) .padding(end = 12.dp) .size(12.dp) .rotate(iconRotation) ) } ExposedDropdownMenu( expanded = isExpanded, onDismissRequest = { isExpanded = false }, ) { items.forEachIndexed { i, item -> DropdownMenuItem( content = item, onClick = { onChange(i) isExpanded = false } ) } } } } @OptIn(ExperimentalMaterialApi::class) @Composable fun DynamicSelectTextField( selectedValue: String, options: List<String>, label: String, onValueChangedEvent: (String) -> Unit, modifier: Modifier = Modifier ) { var expanded by remember { mutableStateOf(false) } ExposedDropdownMenuBox( expanded = expanded, onExpandedChange = { expanded = !expanded }, modifier = modifier ) { OutlinedTextField( readOnly = true, value = selectedValue, onValueChange = {}, label = { Text(text = label) }, trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) }, modifier = Modifier .fillMaxWidth() ) ExposedDropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) { options.forEach { option: String -> DropdownMenuItem( content = { Text(text = option) }, onClick = { expanded = false onValueChangedEvent(option) } ) } } } }
使用示例
CustomExposedDropDown( label = { TranslatedText(Translation.SUGGESTED_SERVERS.msg()) }, items = serverOptions.map { { Text(it.displayName) } }, onChange = { screenModel.setSuggestedServer(serverOptions[it]) }, modifier = Modifier .width(200.dp) .align(Alignment.CenterHorizontally) .padding(bottom = 10.dp) )
已尝试的解决方法
- 更新所有依赖;
- 实现两种不同类型的下拉菜单。
解决方案
1. 移除CustomExposedDropDown中的空clickable回调
CustomExposedDropDown内的Box设置了空的.clickable(onClick = {}),会拦截点击事件并干扰菜单选项的交互逻辑。直接移除该clickable修饰符即可:
Box( contentAlignment = Alignment.Center, modifier = Modifier .fillMaxWidth() .heightIn(min = 36.dp) .background( color = MaterialTheme.colors.onSurface.copy(alpha = TextFieldDefaults.BackgroundOpacity), shape = RoundedCornerShape(10.dp) ) // 移除 .clickable(onClick = {}) )
2. 用rememberSaveable替代remember保存展开状态
Voyager导航可能导致页面重组时状态丢失,改用rememberSaveable持久化展开状态,避免交互异常:
// 原代码 var isExpanded by remember { mutableStateOf(false) } // 修改为 var isExpanded by rememberSaveable { mutableStateOf(false) }
该修改需同时应用在CustomExposedDropDown和DynamicSelectTextField两个组件中。
3. 确保菜单锚点关联正确
若使用Material3版本的Compose,需给ExposedDropdownMenu添加.menuAnchor()修饰符,确保与ExposedDropdownMenuBox的布局上下文正确关联:
ExposedDropdownMenu( expanded = isExpanded, onDismissRequest = { isExpanded = false }, modifier = Modifier.menuAnchor() ) { // 菜单选项内容 }
4. 排查布局遮挡问题
检查父布局是否存在透明覆盖层、高优先级的pointerInput或其他点击拦截逻辑,确保ExposedDropdownMenu的层级处于最上层,没有被其他布局遮挡。
内容的提问来源于stack exchange,提问作者SehrGuterCode
相关产品推荐
相关产品推荐

