今天开发Flutter
时又碰到一个小问题,如何将自定义SVG
图标设置到Icon
或者说IconData
。本以为是一个很简单需求,也搜索到同类需求的 how to import a svg icon to icondata,但回答都没解决这个问题。
花了点时间,终于梳理出这个需求的一些要点,这里分享给有需要的人。
Widget、Icon 和 IconData
首先我们要区别Widget
、Icon
和IconData
,因为很多人觉得 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
。
Icon
和IconData
它们可以当成一类,都是图标,而且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 Design
的IconData
。在上面代码使用的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/