如何在Jetpack Compose中实现如图所示的Exposed下拉菜单?
效果展示


实现Exposed下拉菜单的简便方案
这种外露式下拉菜单是Material Design规范中的标准组件,各平台都有官方封装的现成组件,不用从零开发:
1. Android 平台
方式一:Jetpack Compose(推荐)
Compose直接提供ExposedDropdownMenuBox组件,开箱即用:
@Composable fun ExposedDropdownSample() { val options = listOf("选项1", "选项2", "选项3", "选项4") var expanded by remember { mutableStateOf(false) } var selectedOptionText by remember { mutableStateOf(options[0]) } ExposedDropdownMenuBox( expanded = expanded, onExpandedChange = { expanded = !expanded } ) { TextField( readOnly = true, value = selectedOptionText, onValueChange = {}, label = { Text("选择选项") }, trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) }, colors = ExposedDropdownMenuDefaults.textFieldColors() ) ExposedDropdownMenu( expanded = expanded, onDismissRequest = { expanded = false } ) { options.forEach { option -> DropdownMenuItem( text = { Text(option) }, onClick = { selectedOptionText = option expanded = false } ) } } } }
引入Compose Material依赖后,直接复用组件即可,自带展开/收起动画与Material样式。
方式二:View 系统(AppCompat)
用MaterialAutoCompleteTextView实现,无需自定义弹窗:
<!-- 布局文件 --> <com.google.android.material.textfield.TextInputLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="选择选项"> <com.google.android.material.textfield.MaterialAutoCompleteTextView android:id="@+id/auto_complete_tv" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="none"/> </com.google.android.material.textfield.TextInputLayout>
// 代码逻辑 String[] options = {"选项1", "选项2", "选项3", "选项4"}; MaterialAutoCompleteTextView autoCompleteTV = findViewById(R.id.auto_complete_tv); ArrayAdapter<String> adapter = new ArrayAdapter<>(this, R.layout.dropdown_menu_item, options); autoCompleteTV.setAdapter(adapter);
2. Web 前端
Material UI(React)
用官方Select组件直接实现:
import * as React from 'react'; import Box from '@mui/material/Box'; import InputLabel from '@mui/material/InputLabel'; import MenuItem from '@mui/material/MenuItem'; import FormControl from '@mui/material/FormControl'; import Select from '@mui/material/Select'; export default function ExposedDropdown() { const [selected, setSelected] = React.useState(''); const handleChange = (event) => { setSelected(event.target.value); }; return ( <Box sx={{ minWidth: 120 }}> <FormControl fullWidth> <InputLabel id="select-label">选择选项</InputLabel> <Select labelId="select-label" id="simple-select" value={selected} label="选择选项" onChange={handleChange} > <MenuItem value="opt1">选项1</MenuItem> <MenuItem value="opt2">选项2</MenuItem> <MenuItem value="opt3">选项3</MenuItem> </Select> </FormControl> </Box> ); }
Bootstrap
引入Bootstrap CSS后,直接用form-select:
<div class="mb-3"> <label for="dropdown-select" class="form-label">选择选项</label> <select class="form-select" id="dropdown-select"> <option>选项1</option> <option>选项2</option> <option>选项3</option> <option>选项4</option> </select> </div>
总结
这类菜单的核心是「文本框+下拉弹窗」组合,直接使用各平台官方UI框架提供的封装组件是最简便的方式,无需自己实现动画、交互逻辑和样式适配。
内容的提问来源于stack exchange,提问作者HighBinder
相关产品推荐
相关产品推荐

