FlutterUnit 工具集录 | IconFont 类代码自动生成
Posted datian1234
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了FlutterUnit 工具集录 | IconFont 类代码自动生成相关的知识,希望对你有一定的参考价值。
1. IconFont 类代码生成器的作用
首先介绍一下 FlutterUnit 中,代码生成菜单下的 IconFont
工具的作用。它主要解决Flutter 项目中自定义字体图标使用的问题:
- 字体图标调用类代码的
自动生成
。 - pubspec.yaml 中字体图标节点的
自动配置
。 多个
自定义字体图标节点的支持。
一键自动生成相关代码和配置,在项目中直接使用生成类调用:
2. 使用方式
如下是 FlutterUnit 中的交互界面,选择相关资源后,点击 生成代码 即可。该功能在新版的 FlutterUnit 桌面版: windows/macos 中可以使用。FlutterUnit 是一个 github 开源项目,可在主页中下载安装包。
如果不想下载软件,也可以使用项目中的 icon_font_class_parser.dart 作为脚本,提供配置来使用。
3. 使用步骤
- [1]. 在 iconfont.cn 挑选图标,加入项目,下载压缩包。
- [2]. 选择目标 Flutter 项目地址,配置资源、产物文件位置。
- [3]. 点击生成代码按钮
二、工具实现过程中的技术点
这个工具虽小,但包含着很多的知识。下面来分享一下实现过程中使用的技术点,以及碰到的问题以及解决方式。
1. 文件的解压
本着尽可能减少使用者操作的原则,工具中直接读取压缩包,省去使用者自己解压的步骤。解压使用的是三方库: archive
解压过程中主要做的是两件事,其一:寻找 ttf
文件,将其拷贝到目标地址; 其二: 寻找 json
文件,将其读取出来,解析生成调用类代码,其中 tag1 处是解压过程中,获取文件数据,转化为字符串:
final inputStream = InputFileStream(config.srcZip);
// 将压缩包有用资源解压到目标文件
final archive = ZipDecoder().decodeBuffer(inputStream);
for (var file in archive.files)
if (file.isFile)
if (file.name.endsWith('.ttf'))
final outputStream = OutputFileStream(config.ttfDistPath);
file.writeContent(outputStream);
outputStream.close();
if (file.name.endsWith('.json'))
dynamic data = file.content; // tag1
String jsonContent = utf8.decode(data);
String resultCode = parser(jsonContent,config.fontFamily);
File distFile = File(config.distFilePath);
if(!distFile.existsSync())
distFile.createSync(recursive: true);
distFile.writeAsStringSync(resultCode);
setYaml(config);
2. 文件选择器
文件选择器使用的是三方库: file_picker
该库支持选择文件夹 getDirectoryPath
和选择文件 pickFiles
, 使用起来还是非常方便的。
void _showSelectFile() async
String? path;
if (pickerDir)
path = await FilePicker.platform.getDirectoryPath();
else
FilePickerResult? result = await FilePicker.platform.pickFiles();
if (result != null)
path = result.files.single.path;
3. json 文件的解析以及类代码的生成
这点是最核心的逻辑, 压缩包中的 iconfont.json
文件中记录了 名称
和 Unicode
码的映射关系。这里要做的就是提取这些关键数据,生成 Dart 代码。
逻辑也非常简单,就是字符串的拼接而已,根基映射关系生成一条条的静态常量字符串。不到 20 行代码就完成了最核心的代码生成逻辑。
String parser(String input,String fontFamily)
dynamic map = json.decode(input);
List<dynamic> glyphs = map['glyphs'] as List<dynamic>;
String code = '';
for(int i=0;i<glyphs.length;i++)
String fieldName = glyphs[i]['font_class'];
String unicode = glyphs[i]['unicode'];
String lineCode = """static const IconData $fieldName = IconData(0x$unicode, fontFamily: "$fontFamily");\\n""";
code+=lineCode;
String result =
"""
import 'package:flutter/widgets.dart';
// Power By 张风捷特烈--- Generated file. Do not edit.
// 欢迎支持: https://github.com/toly1994328/FlutterUnit
class $fontFamily
$fontFamily._();
$code
""";
return result;
4. pubspec.yaml 的自动配置
pubspec.yaml 自动配置图标字体对应的节点,这也是尽可能让使用者减少操作的步骤。 这个工具是在直播时写的,这个功能是耗费时间多的地方。
首先这是一个 yaml
文件,很自然会想到使用 yaml
解析器,修改节点。但使用这种方式存在一个问题: 所有的注释信息在重新生成时会被抹除。这就不得不寻求其他的出路。最终的方案是 正则匹配,如下所示 ^ +- family: +(\\w+)
可以匹配到所有的 family
行:
在配置过程中会有一些情况,比如初始项目中没有 fonts
节点,或者已经配置过了这个字体图标。需要分情况处理,流程图如下:
采取读行的方式读取文件,通过正则匹配使用存在 fonts
节点,如果没有在 flutter
所在行的下一行添加配置信息:
List<String> lines = pubspecFile.readAsLinesSync();
RegExp fontsRegex = RegExp(r'^ fonts:',multiLine: true);
bool hasFonts = fontsRegex.hasMatch(lines.join('\\n'));
if(!hasFonts)
// 当前没有 fonts 节点,需要添加到 flutter 节点下
int index = lines.indexWhere((e) => e.startsWith('flutter:'));
List<String> fonts = [
' fonts:',
' - family: $familyName',
' fonts:',
' - asset: $fontAssetsDist',
];
lines.insertAll(index+1, fonts);
pubspecFile.writeAsStringSync(lines.join('\\n'));
return;
当 fonts 节点存在,查询 family ,有没有当前字体图标, 如果没有在 fonts 节点下一行添加配置:
// 存在 fonts 节点,查询 family ,有没有当前字体图标
bool hasTargetFamily = false;
RegExp regExp = RegExp(r'^ +- family: +(\\w+)');
for(int i=0;i<lines.length;i++)
String line = lines[i];
if(line.startsWith(regExp))
String family = regExp.allMatches(line).first.group(1)??'';
if(family == familyName)
hasTargetFamily = true;
break;
if(!hasTargetFamily)
int index = lines.indexWhere((e) => e.startsWith(fontsRegex));
List<String> fonts = [
' - family: $familyName',
' fonts:',
' - asset: $fontAssetsDist',
];
lines.insertAll(index+1, fonts);
pubspecFile.writeAsStringSync(lines.join('\\n'));
到这里就完成了核心功能,感兴趣的可以根据源码调试分析看看。最后,欢迎大家多多关注 FlutterUnit 项目。那本文就到这里,谢谢观看 ~
作者:张风捷特烈
链接:https://juejin.cn/post/7203752514843836471
最后
如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。
如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。
全套视频资料:
一、面试合集
二、源码解析合集
三、开源框架合集
欢迎大家一键三连支持,若需要文中资料,直接点击文末CSDN官方认证微信卡片免费领取↓↓↓
以上是关于FlutterUnit 工具集录 | IconFont 类代码自动生成的主要内容,如果未能解决你的问题,请参考以下文章
烧录神器AVRDUDESS 带图形界面烧录工具 AVRDUDE
ESP8266 NodeMCU-PyFlasher烧录工具的使用
Error: Could not find the correct Provider<GlobalBloc> above this BlocBuilder<GlobalBloc, GlobalStat