【问题标题】:Custom font is not rendered to golden images when package is provided提供包时,自定义字体不会呈现为金色图像
【发布时间】:2020-06-22 06:18:37
【问题描述】:

我在模块theme 中定义了一个自定义字体。该模块是模块widgets 中的一个依赖项。

小部件模块中的小部件应用自定义字体,如下所示

style: TextStyle(
  fontSize: fontSize,
  fontFamily: "IconActions",
  package: "theme"
)

效果很好。

不幸的是,这种自定义字体没有呈现在金色图像上。我必须删除 package: "theme" 来解决这个问题。但这会破坏应用程序并且不再显示字体。 所以基本上我可以让字体在生产代码或测试代码中正常工作,但不能同时使用。

自定义字体在测试的setUp方法中加载

final fontData = File('assets/fonts/IconActions.ttf')
  .readAsBytes()
  .then((bytes) => ByteData.view(Uint8List.fromList(bytes).buffer));
final fontLoader = FontLoader('IconActions')..addFont(fontData);
await fontLoader.load();

是我遗漏了什么,还是一个错误?

【问题讨论】:

    标签: flutter flutter-test


    【解决方案1】:

    去年我遇到了这个确切的问题,也无法在测试中加载字体。不知道具体是 package 参数破坏了它,所以感谢您更新结果。

    至于另一种解决方法,有一种两全其美的方法,您可以拥有独立的字体包,而不必在使用它的应用中声明打包的字体文件。

    例如,我们有一个公司品牌/排版包,我们在多个应用程序中使用它,其中包含我们所有预配置的 TextStyle 声明,另一个独立包具有自定义生成的 IconData 存储在 @987654324 中@ 文件(如 FontAwesome)。

    包装方面:

    pubspec.yaml

    
    flutter:
      uses-material-design: true
      assets:
        - assets/fonts/
      fonts:
        - family: MyFont
          fonts:
            - asset: assets/fonts/MyFont.ttf
              weight: 400
    
        # etc
    
    

    打包后的TextStyle

    class BrandStyles {
      static const _packageName = '<package_name>';
    
      static const headline1Style = TextStyle(
        color: Colors.black,
        fontFamily: 'MyFont',
        fontSize: 60.0,
        fontStyle: FontStyle.normal,
        fontWeight: FontWeight.w400,
        height: 1.16,
        letterSpacing: 0,
        package: _packageName,
      );
    
    
      // etc
    
    }
    

    黄金测试

    void main() {
      final widget = MaterialApp(
        theme: ThemeData(
          textTheme: TextTheme(
            // use custom extension method to remove `package` value
            headline1: BrandStyles.headline1Style.trimFontPackage(),
          ),
        ),
        home: Scaffold(
          body: SafeArea(child: StylesExample()),
        ),
      );
    
      setUp(() async {
        TestWidgetsFlutterBinding.ensureInitialized();
        final file = File('path/to/packaged/asset/MyFont.ttf').readAsBytesSync();
        final bytes = Future<ByteData>.value(file.buffer.asByteData());
    
        await (FontLoader('MyFont')..addFont(bytes)).load();
      });
    
      testWidgets('Golden typography test', (WidgetTester tester) async {
        await tester.pumpWidget(widget);
        await expectLater(
            find.byType(MaterialApp), matchesGoldenFile('goldens/typography.png'));
      });
    }
    
    extension StylingExtensions on TextStyle {
      
      TextStyle trimFontPackage() {
        return TextStyle(
          inherit: inherit,
          color: color,
          backgroundColor: backgroundColor,
          fontSize: fontSize,
          fontWeight: fontWeight,
          fontStyle: fontStyle,
          letterSpacing: letterSpacing,
          wordSpacing: wordSpacing,
          textBaseline: textBaseline,
          height: height,
          locale: locale,
          foreground: foreground,
          background: background,
          shadows: shadows,
          fontFeatures: fontFeatures,
          decoration: decoration,
          decorationColor: decorationColor,
          decorationStyle: decorationStyle,
          decorationThickness: decorationThickness,
          debugLabel: debugLabel,
          /// `replaceAll` only required if loading multiple fonts, 
          /// otherwise set value to your single `fontFamily` name
          fontFamily: fontFamily.replaceAll('packages/<package_name>/', ''),
        );
      }
    }
    

    或者,如果像我一样,您对自定义图标也有同样的问题,可以在您的自定义 IconData 的黄金测试中使用类似的扩展方法完成相同的操作,删除 fontPackage 值:

    extension IconExtensions on IconData {
      IconData convertToGolden() => IconData(
            this.codePoint,
            fontFamily: this.fontFamily,
          );
    }
    
    

    您的应用端

    pubspec.yaml

    
    # ...
    
    dependencies:
      flutter:
        sdk: flutter
    
      <package_name>:
        git:
          url: <url_to_hosted_package>.git
          ref: <release_tag>
    
    

    main.dart

    
    class MyApp extends StatelessWidget {
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData.light().copyWith(
            textTheme: TextTheme(
              headline1: BrandStyles.headline1Style,
            ),
          ),
        );
      }
    
    }
    

    现在不再需要在您的应用程序pubspec.yaml 中声明您的字体,甚至无需将样式包与您的实施应用程序放在同一个项目/存储库中。

    【讨论】:

      【解决方案2】:

      所以基本上解决方案是从 TextStyle 中删除 package: "theme" 以使其工作。但这只是解决方案的一半,因为正如我在问题中提到的,现在黄金文件具有正确的字体渲染器,但字体在应用程序中不起作用。

      为了让它在应用中工作,我们需要给定项目结构:

      pubspec.yaml(模块theme

      flutter:
        fonts:
         - family 'ComicSans'
           fonts:
           - asset: packages/theme/fonts/ComicSans.ttf
      

      widget.dart(模块theme

      style: TextStyle(
        fontSize: fontSize,
        fontFamily: "ComicSans",
      )
      

      现在在模块widgets 中,即包含main.dart 的模块以及您运行的main 函数,您必须再次定义字体:

      pubspec.yaml(模块widgets

      dependencies:
        flutter:
          sdk: flutter
        theme:
          path: ../path/to/theme/module
      
      flutter:
        fonts:
         - family 'ComicSans'
           fonts:
           - asset: packages/theme/fonts/ComicSans.ttf
      

      现在字体在应用程序和金色图像中都正确显示了。

      【讨论】:

        猜你喜欢
        • 2021-10-07
        • 1970-01-01
        • 1970-01-01
        • 2013-06-16
        • 2016-02-23
        • 2016-05-30
        • 1970-01-01
        • 2011-09-09
        • 2015-03-28
        相关资源
        最近更新 更多