Jetpack Compose ExposedDropdownMenu高度超20dp时总是向上展开问题
我在实现ExposedDropdownMenu,希望它显示在TextField下方。但发现只要下拉菜单高度超过20dp,它就会向上展开,只有高度≤20dp时才会正常向下显示。
效果展示:
我的代码:
@OptIn(ExperimentalMaterial3Api::class) @Composable fun TextFieldWithDropdown( modifier: Modifier = Modifier, textFieldState: TextFieldState, textCallback: (String) -> Unit, list: List<String>, keyboardOptions: KeyboardOptions, textStyle: TextStyle ) { val dropDownOptions = remember { mutableStateOf(listOf<String>()) } val textFieldValue = remember { mutableStateOf(TextFieldValue()) } val dropDownExpanded = remember { mutableStateOf(false) } ExposedDropdownMenuBox( modifier = modifier, expanded = dropDownExpanded.value, onExpandedChange = { dropDownExpanded.value = !dropDownExpanded.value }) { TextField( modifier = Modifier .menuAnchor() .fillMaxWidth() .onFocusChanged { focusState -> if (!focusState.isFocused) dropDownExpanded.value = false }, value = textFieldState.text.value, onValueChange = { textFieldState.text.value = it textCallback.invoke(it) dropDownOptions.value = list.filter { it.startsWith(textFieldState.text.value) && it != textFieldState.text.value } .take(3) dropDownExpanded.value = dropDownOptions.value.isNotEmpty() }, singleLine = true, maxLines = 1, textStyle = textStyle, ) ExposedDropdownMenu( expanded = dropDownExpanded.value, onDismissRequest = { dropDownExpanded.value = false }, ) { dropDownOptions.value.forEach { text -> DropdownMenuItem(text = { Text(text = text) }, onClick = { textFieldState.text.value = text dropDownExpanded.value = false }) } } } }
解决方案
问题原因
ExposedDropdownMenu默认会根据屏幕可用空间自动调整展开方向:当TextField下方的剩余空间不足以容纳菜单高度时,组件会自动切换为向上展开。高度超过20dp时,当前布局下方的空间刚好不足以容纳菜单,触发了这个自动适配逻辑。
解决方法
1. 强制固定展开方向
给ExposedDropdownMenu添加对齐方式和偏移参数,强制菜单从TextField底部向下展开:
ExposedDropdownMenu( expanded = dropDownExpanded.value, onDismissRequest = { dropDownExpanded.value = false }, // 强制菜单顶部与TextField底部对齐 expandedAlignment = Alignment.TopStart, // 偏移量设置为TextField的高度,确保菜单紧贴下方 expandedOffset = DpOffset(0.dp, TextFieldDefaults.MinHeight) ) { dropDownOptions.value.forEach { text -> DropdownMenuItem(text = { Text(text = text) }, onClick = { textFieldState.text.value = text dropDownExpanded.value = false }) } }
2. 确保父布局有足够空间
检查TextFieldWithDropdown的父布局约束:
- 如果父布局是
Column,可以添加滚动让内容能向下扩展:
Column(modifier = Modifier.verticalScroll(rememberScrollState())) { TextFieldWithDropdown(/* 参数 */) }
- 避免父布局设置固定高度或被其他组件挤压,保证TextField下方有足够空间容纳菜单。
3. 限制菜单高度并启用内部滚动
既保证显示足够选项,又避免菜单高度过大触发向上展开:
ExposedDropdownMenu( expanded = dropDownExpanded.value, onDismissRequest = { dropDownExpanded.value = false }, // 限制菜单最大高度,超出部分内部滚动 modifier = Modifier.maxHeight(150.dp).verticalScroll(rememberScrollState()) ) { dropDownOptions.value.forEach { text -> DropdownMenuItem(text = { Text(text = text) }, onClick = { textFieldState.text.value = text dropDownExpanded.value = false }) } }
内容的提问来源于stack exchange,提问作者voximdo
相关产品推荐
相关产品推荐

