在 Flutter3.0 之后,Dart 版本到 2.17 。虽然知道 Dart 枚举已支持属性成员,但一直没有用过。最近刚好有个使用的小场景,就来介绍一下。将以如下的 PopupMenuButton 的按钮数据来介绍:
本文视频版:
也可以在 bilibili 观看: www.bilibili.com/video/BV1AN...
1. 枚举对成员的支持
在以前,枚举的特性比较贫弱,只能定义一个个元素。 如下所示,定义一个 MenuAction
用于表示菜单的类型:
dart
enum MenuAction {
setting,
about,
help,
}
如果想要根据枚举元素,得到对应的介绍文字就比较麻烦,需要维护一组元素和字符串的映射关系。所以当枚举可以支持成员属性,就非常友好。代码如下:
dart
enum MenuAction {
setting(label: '应用设置'),
about(label: '关于应用'),
help(label: '帮助中心');
final String label;
const MenuAction({
required this.label,
});
}
这里需要注意三个小细节:
[1]. 枚举区代码一定要在成员和构造之上。
[2]. 最后一个枚举元素以
;
结尾,其余的枚举元素以,
结尾。[2]. 枚举的构造函数 一定要是 const 构造。
2. PopupMenuButton 的使用
PopupMenuButton 可以支持一个泛型,这里设置为 MenuAction
。这样构建的 PopupMenuEntry
泛型也将是 MenuAction
,其中条目的文字就可以通过 action.label 获取,非常方便:
dart
class MorePopIcon extends StatelessWidget {
const MorePopIcon({super.key});
@override
Widget build(BuildContext context) {
return PopupMenuButton<MenuAction>(
itemBuilder: _buildItem,
onSelected: _onTapItem,
icon: const Icon(Icons.more_vert_outlined),
position: PopupMenuPosition.under,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(10)),
),
);
}
List<PopupMenuEntry<MenuAction>> _buildItem(BuildContext context) {
return MenuAction.values
.map((MenuAction action) => PopupMenuItem<MenuAction>(
height: 35,
value: action,
child: Center(child: Text(action.label)),
))
.toList();
}
}
在点击条目触发的回调中,可以得到对应的 MenuAction
枚举元素,通过 switch
关键字就可以很轻松地进行处理:
dart
void _onTapItem(MenuAction value) {
switch(value){
case MenuAction.setting:
break;
case MenuAction.about:
showConformDialog();
break;
case MenuAction.help:
break;
}
}
3. 支持图标
现在想要为菜单栏添加图标,可以为 MenuAction 增加成员来实现。代码如下:
dart
enum MenuAction {
setting(label: '应用设置',iconData: Icons.settings),
about(label: '关于应用',iconData: Icons.info),
help(label: '帮助中心',iconData: Icons.help);
final String label;
final IconData iconData;
const MenuAction({
required this.label,
required this.iconData,
});
}
构建条目组件时,使用 MenuAction 对象中的 iconData 即可:
4. 枚举支持实现和定义方法
最后,枚举中可以提供方法,包括运算符重载;也支持 implements
关键字实现一个接口。如下所示,MenuAction 实现 Comparable 接口,并实现 compareTo 方法,拥有比较的能力。然后重写了 >
运算符,支持两个元素之间的比较。
dart
void main() {
bool b = MenuAction.help > MenuAction.about;
print(b);
}
enum MenuAction implements Comparable<MenuAction> {
setting(label: '应用设置', iconData: Icons.settings),
about(label: '关于应用', iconData: Icons.info),
help(label: '帮助中心', iconData: Icons.help);
final String label;
final IconData iconData;
const MenuAction({
required this.label,
required this.iconData,
});
@override
int compareTo(MenuAction other) => label.compareTo(other.label);
bool operator >(MenuAction other) {
return compareTo(other) > 0;
}
}
总的来说,Dart 枚举支持成员属性和方法的特性是一个很便捷的特性,能让代码更简洁。那么本文接到这了,谢谢观看~