theme: cyanosis
1. 前言
Flutter 框架中新增了 DropdownMenu 下拉按钮,可以让我们更方便地实现下拉选择的交互。本文案例源码可以详见 【FlutterUnit 的 DropdownMenu】
2. DropdownMenu 基础使用
首先通过一个最简单的案例体验一下 DropdownMenu 的使用,如下所示: - 点击使会下拉展示菜单选项,选择科目 ; - 点击时选中科目,下方的文本相应变化; - 支持输入定位到指定的菜单条目;
实现的代码如下,
| 参数名 | 类型 | 介绍 | --- | --- |--- | | dropdownMenuEntries |
```dart class DropdownMenuNode1 extends StatefulWidget { const DropdownMenuNode1({super.key});
@override State
createState() => _DropdownMenuNode1State(); }
class _DropdownMenuNode1State extends State
{ final List
data = ['语文', '数学', '英语', '物理', '化学', '生物', '地理']; late String _dropdownValue = data.first;
@override Widget build(BuildContext context) { return Column( mainAxisSize: MainAxisSize.min, children: [ DropdownMenu
( menuHeight: 200, initialSelection: data.first, onSelected:
onSelect, dropdownMenuEntries: _buildMenuList(data), ), const SizedBox(height: 8,), Text('你选择的学科是: $dropdownValue') ], ); }
void _onSelect(String? value) { setState(() { _dropdownValue = value!; }); }
List
> _buildMenuList(List
data) { return data.map((String value) { return DropdownMenuEntry
(value: value, label: value); }).toList(); } } ```
3. DropdownMenu 样式配置
DropdownMenu 本质上是由 TextField + MenuAnchor 实现的,所以样式配置上面主要和这两个组件有关。
| 参数名 | 类型 | 介绍 | --- | --- |--- | | controller |
下面是右侧选择图标的 DropdownMenu 组件构建逻辑,其中
- requestFocusOnTap: 点击时是否获取焦点,置为 true 在移动端上会弹出软键盘,桌面端无法输入。
- enableFilter: 弹出菜单项是否以当前内容搜索,如果为 true, 会因为过滤使得菜单响应减少。
下面是左侧选择颜色的 DropdownMenu 组件构建逻辑,其中
- menuStyle 可以调节菜单面板的样式,比如背景色、边距、最大最小尺寸、形状等。
- dropdownMenuEntries 中可以通过 DropdownMenuEntry 的 enable 参数设置是否禁用菜单项。
```dart Widget _buildColorMenu(){ return DropdownMenu
( initialSelection: ColorLabel.green, controller: colorController, requestFocusOnTap: true, label: const Text('Color'), menuHeight: 150, menuStyle: const MenuStyle( backgroundColor: MaterialStatePropertyAll
(Colors.white), surfaceTintColor: MaterialStatePropertyAll
(Colors.white), padding: MaterialStatePropertyAll
(EdgeInsets.symmetric(vertical: 20)), ), onSelected: (ColorLabel? color) { setState(() { selectedColor = color; }); }, dropdownMenuEntries: ColorLabel.values.map((ColorLabel color) { return DropdownMenuEntry
( value: color, label: color.label, enabled: color.label != 'Grey', style: MenuItemButton.styleFrom( foregroundColor: color.color, ), ); } ).toList(), ); }
```
另外,如果 DropdownMenu 的菜单条目比较复杂,想要定制展示内容,可以通过 DropdownMenuEntry 的 labelWidget 构建,如下所示,根据
```dart class _UserItem extends StatelessWidget { final User user;
const _UserItem({ Key? key, required this.user, }) : super(key: key);
@override Widget build(BuildContext context) { return Container( padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 6), child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ CircleAvatar( foregroundColor: Colors.transparent, backgroundImage: AssetImage('assets/images/head_icon/${user.image}'), ), const SizedBox(width: 20), Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ Text(user.name), Text( '性别: ${user.man ? '男' : '女'}', style: const TextStyle(color: Colors.grey), ), ], ), ], ), ); } } ```
到这里,DropdownMenu 组件使用相关的属性就介绍的差不多了。下面来简单瞄一眼 DropdownMenu 的代码实现。
4. DropdownMenu 源码实现简看
DropdownMenu 是一个
从构建逻辑上来看最主要依赖
其中
其中最核心的视图表现是对 MenuAnchor 组件的封装,在 builder 回调中构建输入框、首尾按钮等展示内容。内容的排列通过
其中 menu 对象是通过
DropdownMenu 的核心逻辑也就这些,它是对