如何在 Flutter 使用自定义图标 Icon

今天开发Flutter时又碰到一个小问题,如何将自定义SVG图标设置到Icon或者说IconData。本以为是一个很简单需求,也搜索到同类需求的 how to import a svg icon to icondata,但回答都没解决这个问题。

花了点时间,终于梳理出这个需求的一些要点,这里分享给有需要的人。

Widget、Icon 和 IconData

首先我们要区别WidgetIconIconData,因为很多人觉得 Flutter加载SVG图片是很简单的事,也确实,依赖flutter_svg,然后读取就行。

  # 加载SVG图片 https://pub.flutter-io.cn/packages/flutter_svg
  flutter_svg: 1.1.6
  
  SvgPicture.asset()

但这里返回的结果是Widget,如果你需要的是Icon或者IconData,它是不能使用的SvgPicture can't be assigned to Icon

IconIconData它们可以当成一类,都是图标,而且Icon是由IconData构造的,可以理解两者之间可以互相转换。

static const IconData abc = IconData(0xf04b6, fontFamily: 'MaterialIcons');

Icon icon = Icon(Icons.abc);
IconData? iconData = Icon(Icons.abc).icon;

所以,关键是IconData,那这个需求就被拆解成,如何从自定义SVG获取IconData

自定义 IconData

Flutter 内置了一套 Material DesignIconData。在上面代码使用的Icons.abc就是,但这些都是系统级,可能存在不够用的情况,而且大部分公司都有自己设计的图标,这才需要使用自定义 Icon 图标。

这里有个工具网站 FlutterIcon – Flutter custom icons generator,它提供了很多图标,如果内置图标不够用,可以在这找到需要的。

假设找到这 4 个是项目需要的,先别急下载。点击Names重命名。

对着图标重命名,这里的名字是项目中使用这个图标时引用的名字。比如这里的threedee_rotation,那在代码中要用这个图标就是如下。

static const IconData threedee_rotation = IconData(0xe800, fontFamily: _kFontFam, fontPackage: _kFontPkg);

Icon icon = Icon(R.threedee_rotation);

所以,这个名字影响项目中实际使用此图标的命名。第二个名字CustomIcon1也建议自己重命名,不要用默认的,它是fontFamilyName,有三个地方用到了。

 flutter:
   fonts:
    - family:  CustomIcon1
      fonts:
       - asset: fonts/CustomIcon1.ttf

首先,下载到本地的字体图标文件名就是采用这个名字,其次特别重要的fontFamily名字也是用的它。最后,IconData定义时,其中一个参数需要填写fontFamily,它的值也是下载时填写的名字。

  static const _kFontFam = 'CustomIcon1';
  static const String? _kFontPkg = null;

  static const IconData threedee_rotation = IconData(0xe800, fontFamily: _kFontFam, fontPackage: _kFontPkg);

如果上面代码看不清,可以简写成如下:

	static const IconData threedee_rotation = IconData(0xe800, fontFamily: "CustomIcon1", fontPackage: null);

OK,这就获取到 IconData了。但不对啊,这里我们还是用网上资源,并不是我们自定义图标。其实上面工具,也提供上传自己的SVG图标,转换下载成图标字体.ttf的功能。

重复上面步骤,不过多了一步上传SVG

但这是理想状况,实际情况,我们的图标并不是一次性上传,然后下载图标字体.ttf,配置图标。可能先做某个功能,需要用到一些图标,就上传、生成、配置。过了几天,又需要自定义另外一些图标,又来上传下载。

所以,我建议fontFamily按照数字序号命名,因为可能要在pubspec.ymal配置多次,完整代码如下。

flutter:
  uses-material-design: true

  fonts:
    - family:  CustomIcon1
      fonts:
        - asset: assets/fonts/CustomIcon1.ttf
    - family: CustomIcon2
      fonts:
        - asset: assets/fonts/CustomIcon2.ttf
        
  static const IconData treeview_menu_parent = IconData(0xe800, fontFamily: "CustomIcon1", fontPackage: null);
  static const IconData treeview_menu_child = IconData(0xe800, fontFamily: "CustomIcon2", fontPackage: null);

当然,可能存在很多图标,上面CustomIcon1建议抽取成变量。然后,貌似引入了新图标文件,要重启整个项目,不能热重载更新。

OK,希望以上能帮到各位,部分参考 How to use custom icons in Flutter

本文由老郭种树原创,转载请注明:https://guozh.net/how-to-use-custom-icons-in-flutter/

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注