Jetpack Compose中ExposedDropDownMenu无法展开显示完整列表
使用Jetpack Compose的ExposedDropDownMenu时,菜单展开后只能显示列表中的第一个条目,尝试将OutlinedTextField的readOnly设为true或false均无法解决问题。编写的完整代码如下:
@OptIn(ExperimentalMaterial3Api::class) @Composable fun Combobox() { val contextForToast = LocalContext.current.applicationContext val listItems = arrayOf("Favorites", "Options", "Settings", "Share") // state of the menu var expanded by remember { mutableStateOf(false) } // remember the selected item var selectedItem by remember { mutableStateOf(listItems[0]) } // box ExposedDropdownMenuBox( expanded = expanded, onExpandedChange = { expanded = !expanded } ) { OutlinedTextField( value = selectedItem, onValueChange = { selectedItem = it }, modifier = Modifier.menuAnchor(), //readOnly = true, label = { Text(text = "Label") }, trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon( expanded = expanded ) }, colors = ExposedDropdownMenuDefaults.textFieldColors() ) // filter options based on text field value val filteringOptions = listItems.filter { it.contains(selectedItem, ignoreCase = true) } if (filteringOptions.isNotEmpty()) { // menu ExposedDropdownMenu( expanded = expanded, onDismissRequest = { expanded = false } ) { // this is a column scope // all the items are added vertically filteringOptions.forEach { selectionOption -> // menu item DropdownMenuItem( text = {Text(text = selectionOption)}, onClick = { selectedItem = selectionOption Toast.makeText(contextForToast, selectedItem, Toast.LENGTH_SHORT).show() expanded = false }, contentPadding = ExposedDropdownMenuDefaults.ItemContentPadding, ) } } } }

解决方法
问题根源在于过滤逻辑错误:当前用selectedItem(已选中的条目)来过滤列表,默认选中第一个条目"Favorites"时,过滤结果只会包含包含该字符串的条目(也就是只有"Favorites"自己),所以菜单仅显示这一项。根据需求可以选择两种修改方式:
方式1:移除过滤,显示所有选项
如果不需要搜索过滤功能,直接去掉过滤逻辑,使用原列表即可:
@OptIn(ExperimentalMaterial3Api::class) @Composable fun Combobox() { val contextForToast = LocalContext.current.applicationContext val listItems = arrayOf("Favorites", "Options", "Settings", "Share") var expanded by remember { mutableStateOf(false) } var selectedItem by remember { mutableStateOf(listItems[0]) } ExposedDropdownMenuBox( expanded = expanded, onExpandedChange = { expanded = !expanded } ) { OutlinedTextField( value = selectedItem, onValueChange = { selectedItem = it }, modifier = Modifier.menuAnchor(), readOnly = true, // 推荐设为true,避免手动输入干扰选中逻辑 label = { Text(text = "Label") }, trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) }, colors = ExposedDropdownMenuDefaults.textFieldColors() ) // 直接使用原列表,移除错误的过滤逻辑 if (listItems.isNotEmpty()) { ExposedDropdownMenu( expanded = expanded, onDismissRequest = { expanded = false } ) { listItems.forEach { selectionOption -> DropdownMenuItem( text = { Text(text = selectionOption) }, onClick = { selectedItem = selectionOption Toast.makeText(contextForToast, selectedItem, Toast.LENGTH_SHORT).show() expanded = false }, contentPadding = ExposedDropdownMenuDefaults.ItemContentPadding, ) } } } } }
方式2:实现实时输入过滤(如需搜索功能)
如果需要根据输入框内容过滤选项,需要将输入文本状态和选中条目状态分开,避免用已选中的条目作为过滤条件:
@OptIn(ExperimentalMaterial3Api::class) @Composable fun Combobox() { val contextForToast = LocalContext.current.applicationContext val listItems = arrayOf("Favorites", "Options", "Settings", "Share") var expanded by remember { mutableStateOf(false) } // 输入框的实时文本 var inputText by remember { mutableStateOf(listItems[0]) } // 最终选中的条目 var selectedItem by remember { mutableStateOf(listItems[0]) } ExposedDropdownMenuBox( expanded = expanded, onExpandedChange = { expanded = !expanded } ) { OutlinedTextField( value = inputText, onValueChange = { inputText = it // 输入时自动展开菜单 expanded = true }, modifier = Modifier.menuAnchor(), readOnly = false, // 允许输入以实现过滤 label = { Text(text = "Label") }, trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) }, colors = ExposedDropdownMenuDefaults.textFieldColors() ) // 用输入框的实时文本过滤列表 val filteringOptions = listItems.filter { it.contains(inputText, ignoreCase = true) } if (filteringOptions.isNotEmpty()) { ExposedDropdownMenu( expanded = expanded, onDismissRequest = { expanded = false } ) { filteringOptions.forEach { selectionOption -> DropdownMenuItem( text = { Text(text = selectionOption) }, onClick = { selectedItem = selectionOption inputText = selectionOption // 同步输入框文本 Toast.makeText(contextForToast, selectedItem, Toast.LENGTH_SHORT).show() expanded = false }, contentPadding = ExposedDropdownMenuDefaults.ItemContentPadding, ) } } } } }
内容的提问来源于stack exchange,提问作者jetberrocal
相关产品推荐
相关产品推荐

