Flutter 知识集锦 | Dart 枚举已支持属性成员

在 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 枚举支持成员属性和方法的特性是一个很便捷的特性,能让代码更简洁。那么本文接到这了,谢谢观看~

相关推荐
xiangxiongfly9151 小时前
Android 圆形和圆角矩形总结
android·圆形·圆角·imageview
幻雨様7 小时前
UE5多人MOBA+GAS 45、制作冲刺技能
android·ue5
Jerry说前后端9 小时前
Android 数据可视化开发:从技术选型到性能优化
android·信息可视化·性能优化
Meteors.9 小时前
Android约束布局(ConstraintLayout)常用属性
android
alexhilton10 小时前
玩转Shader之学会如何变形画布
android·kotlin·android jetpack
whysqwhw14 小时前
安卓图片性能优化技巧
android
风往哪边走14 小时前
自定义底部筛选弹框
android
江上清风山间明月14 小时前
Flutter AlwaysScrollableScrollPhysics详解
flutter·滚动·scrollable·scrollphysics
Yyyy48215 小时前
MyCAT基础概念
android
Android轮子哥15 小时前
尝试解决 Android 适配最后一公里
android