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

相关推荐
朱涛的自习室19 分钟前
逃离“古法测试”:AI 测试的“三大定律”
android·前端·人工智能
QING61826 分钟前
Android面试 —— 八股文(一)
android·面试·android jetpack
带娃的IT创业者37 分钟前
围墙花园的隐形锁:当 reCAPTCHA 拒绝了“去谷歌化”的 Android 用户
android·隐私安全·人机验证·recaptcha·去谷歌化·grapheneos
awu的Android笔记1 小时前
Android 用户态实现 TCP 代理:从 SYN 到 FIN 的完整生命周期
android·tcp/ip
Geek_Vison1 小时前
技术实践:保险健康APP引入第三方小程序实战,如何构建一个安全可控的沙箱环境~
android·安全·小程序·uni-app·mpaas
2501_919749032 小时前
鸿蒙 Flutter 实战:saver_gallery 5.1.0 适配 3.27-ohos 全流程
flutter·华为·harmonyos
2501_915918412 小时前
Python如何抓取HTTPS请求包的完整教程与代码示例
android·ios·小程序·https·uni-app·iphone·webview
. . . . .2 小时前
android开发
android
程序员看世界2 小时前
Kotlin协程是如何实现优先级机制的
android·kotlin
Carson带你学Android2 小时前
Kotlin放大招!官方 Skills 直接喂出「专家级」代码
android·前端·kotlin