Пользовательский шрифт не отображается для золотых изображений, когда предоставляется пакет

У меня есть собственный шрифт, определенный в модуле 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();

Я что-то упускаю или это ошибка?


person tomrozb    schedule 10.03.2020    source источник


Ответы (2)


Итак, в основном решение состоит в том, чтобы удалить package: "theme" из TextStyle, чтобы он работал. Но это половина решения, потому что, как я уже упоминал в вопросе, теперь у золотых файлов средство рендеринга шрифтов правильно, но шрифт не работает в приложении.

Чтобы это работало в приложении, нам нужна заданная структура проекта:

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

Теперь шрифт правильно отображается как в приложении, так и на золотых изображениях.

person tomrozb    schedule 31.03.2020

У меня была именно эта проблема в течение прошлого года, и я также не мог заставить загрузку шрифтов работать во время тестов ... не знал, что именно аргумент package нарушал ее, поэтому спасибо за обновление с таким результатом.

Что касается другого обходного пути, есть способ получить лучшее из обоих миров, когда вы можете иметь свой автономный пакет шрифтов и не объявлять файлы упакованных шрифтов в вашем приложении, которое его использует.

Например, у нас есть пакет фирменной символики / типографии, который мы используем в нескольких приложениях, который содержит все наши предварительно настроенные TextStyle объявления, и еще один автономный пакет, который имеет настраиваемый IconData, который хранится в файле *.ttf (например, 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 или даже иметь пакеты стилей в том же проекте / репозитории, что и ваше реализующее приложение.

person jamie1192    schedule 24.02.2021