flutter - 带有自定义图标字体类的黄金测试
问题描述
我有一个自定义的图标字体 .ttf,我在我的应用程序中使用它作为IconData
,允许以与 Flutter 的内置材质图标相同的方式使用。
我的自定义字体类:
class MyIcons {
MyIcons._();
static const iconFontFamily = 'MyIcons';
static const iconFontPackage = 'my_icon_package';
/// edit_outline
static const IconData edit_outline = IconData(0xe000, fontFamily: iconFontFamily, fontPackage: iconFontPackage);
// etc
}
用法:
Icon(
MyIcons.edit_outline,
size: 24,
)
并且在应用程序中一切正常。但是现在我正在尝试生成黄金测试文件,以确保我的图标在更新 .ttf 后按预期工作,但图标总是只替换为测试 Ahem 字体方块。
如果我使用 Flutter 的默认图标,并uses-material-design: true
在 中设置pubspec.yaml
,这允许默认图标在黄金测试文件中正确呈现,但是无论我尝试什么,我都无法呈现我自己的图标。
我尝试过但没有成功的其他事情:
- eBay 的 Golden_toolkit 包
- 在测试中加载资产
- FontLoader并手动引用图标代码点、fontFamily 和包
有没有办法做到这一点?
解决方案
是的,这是可能的,但是您需要像 Flutter 测试中的任何其他自定义字体一样手动加载图标字体。
我使用了 Flutter Gallery 演示应用程序中的部分解决方案: https ://github.com/flutter/gallery/blob/master/golden_test/testing/font_loader.dart
对于材质图标,我使用了此处找到的解决方案:
问题:https ://github.com/flutter/flutter/issues/75391
代码:https ://github.com/flutter/flutter/pull/74131/files
一些问题是:
- 似乎字体加载必须在测试功能之外完成,所以先执行它然后运行测试。
- 确保文件名和字体系列在任何地方都是正确的。
鉴于有一个正确设置的自定义字体名为“Matter”,并且在项目根目录的“字体”目录中存在正确设置的自定义图标字体 -->
演示代码:
import 'dart:io';
import 'dart:typed_data';
import 'package:[your_path_to_icon_definition_file]/custom_icons.dart';
import 'package:file/file.dart' as f;
import 'package:file/local.dart' as l;
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:path/path.dart' as path;
import 'package:platform/platform.dart' as p;
Future<void> main() async {
await loadFonts();
run();
}
void run() {
group('mobile', () {
testWidgets('Test font and icon loading', (tester) async {
await tester.pumpWidget(MaterialApp(
theme: ThemeData(
fontFamily: 'Matter', // Define the custom font family.
),
home: Scaffold(
appBar: AppBar(
title: Text('AppBar'),
),
body: Column(
children: [
Text('test'),
Icon(CustomIcons.camera), // Custom icon file from for example fluttericon.com
Icon(Icons.add), // material icons ('uses-material-design: true' Must exist in pubspec.yaml)
],
),
),
));
expect(find.byType(MaterialApp), findsOneWidget);
await expectLater(
find.byType(MaterialApp),
matchesGoldenFile('goldens/material_app.png'),
);
});
});
}
/// Load fonts to make sure they show up in golden tests.
Future<void> loadFonts() async {
await _load(await loadFontsFromFontsDir());
await _loadMaterialIconFont();
}
// Loads the cached material icon font.
// Only necessary for golden tests. Relies on the tool updating cached assets before
// running tests.
Future<void> _loadMaterialIconFont() async {
const f.FileSystem fs = l.LocalFileSystem();
const p.Platform platform = p.LocalPlatform();
final flutterRoot = fs.directory(platform.environment['FLUTTER_ROOT']);
final iconFont = flutterRoot.childFile(
fs.path.join(
'bin',
'cache',
'artifacts',
'material_fonts',
'MaterialIcons-Regular.otf',
),
);
final bytes = Future<ByteData>.value(iconFont.readAsBytesSync().buffer.asByteData());
await (FontLoader('MaterialIcons')..addFont(bytes)).load();
}
/// Assumes a fonts dir in root of project
Map<String, List<Future<ByteData>>> loadFontsFromFontsDir() {
final fontFamilyToData = <String, List<Future<ByteData>>>{};
final currentDir = path.dirname(Platform.script.path);
final fontsDirectory = path.join(
currentDir,
'fonts',
);
for (var file in Directory(fontsDirectory).listSync()) {
if (file is File) {
final fontFamily = path.basenameWithoutExtension(file.path).split('-').first;
(fontFamilyToData[fontFamily] ??= []).add(file.readAsBytes().then((bytes) => ByteData.view(bytes.buffer)));
}
}
return fontFamilyToData;
}
Future<void> _load(Map<String, List<Future<ByteData>>> fontFamilyToData) async {
final waitList = <Future<void>>[];
for (final entry in fontFamilyToData.entries) {
print('entry.key=${entry.key}');
final loader = FontLoader(entry.key);
for (final data in entry.value) {
loader.addFont(data);
}
waitList.add(loader.load());
}
await Future.wait(waitList);
}
推荐阅读
- hana-xs - 使用 HANA XS 创建 HANA 数据库并通过 OData 公开它 - 无法使用 Postman 发布
- c# - 如何使用自签名证书创建带有私钥的签名 x509certificate
- alfresco - 用于 Alfresco CMIS 查询的 runAs?
- c# - 解码 Z64 (ZB64) 字符串
- c# - 如何将xaml代码组合成一行
- xlsx - 将数据栏修改为实心填充时,如何阻止其他条件格式消失?
- csv - 需要使用批处理文件将 csv 文件中的所有记录替换为 """
- c# - 在 Windows 窗体中创建 .resource 文件
- python - 为列中的值从原始创建新数据框(需要为每个新数据框更改名称)
- r - 仅保留列表中包含另一个向量 (R) 中的字符串的元素