くらげになりたい。

くらげのようにふわふわ生きたい日曜プログラマなブログ。趣味の備忘録です。

FlutterでGoogle Fontsを扱う(google_fontsパッケージ)

FlutterのYoutubeチャンネルを見てたら、
便利なパッケージがあったので試してみたときの備忘録(*´ω`*)

使い方

とりあえずインストール。

$ fvm flutter pub add google_fonts
$ fvm flutter pub get

アプリ全体のフォントを変える

ThemeDataのtextThemeに設定すればOK

import 'package:google_fonts/google_fonts.dart';
...
  return MaterialApp(
    theme: _buildTheme(Brightness.dark),
  );
}

ThemeData _buildTheme(brightness) {
  var baseTheme = ThemeData(brightness: brightness);

  return baseTheme.copyWith(
    textTheme: GoogleFonts.latoTextTheme(baseTheme.textTheme),
  );
}

GoogleFonts.<フォント名>TextTheme()の形になってる。

一覧は、ソースのgoogle_fonts/lib/google_fonts.dartあたり。
下の方にあるので、検索すると見つけやすい。

個別でフォントを変える

特定のテキストやWidgetだけフォントを変える場合は、
styleに設定すればOK

import 'package:google_fonts/google_fonts.dart';

Text(
  'This is Google Fonts',
  style: GoogleFonts.lato(),
),
// or
Text(
  'This is Google Fonts',
  style: GoogleFonts.lato(
    textStyle: TextStyle(color: Colors.blue, letterSpacing: .5),
  ),
),
// or
Text(
  'This is Google Fonts',
  style: GoogleFonts.lato(textStyle: Theme.of(context).textTheme.headline4),
),

リリース時はassetsのフォントファイルを利用する

google_fontsはネットワーク経由でフォントファイルを取得してくれる。
開発中はよいけど、本番時はアプリに含めてリリースしたい。

フォントファイルをassetsgoogle_fontsというフォルダを用意しておくと、
自動的にそちらを使ってくれる機能があるらしい。

やり方としては、

  1. https://fonts.google.com/ からフォントをダウンロード
  2. zipを展開してstatic/配下のttfファイルをコピー
  3. assets/google_fonts/フォルダを作成して、コピーしたttfファイルを配置
  4. pubspec.yamlassets/google_fonts/を追加
# ダウンロードしたNoto_Sans_JP.zipの展開後
Noto_Sans_JP/
├── NotoSansJP-VariableFont_wght.ttf
├── OFL.txt
├── README.txt
└── static
    ├── NotoSansJP-Black.ttf
    ├── NotoSansJP-Bold.ttf
    ├── NotoSansJP-ExtraBold.ttf
    ├── NotoSansJP-ExtraLight.ttf
    ├── NotoSansJP-Light.ttf
    ├── NotoSansJP-Medium.ttf
    ├── NotoSansJP-Regular.ttf
    ├── NotoSansJP-SemiBold.ttf
    └── NotoSansJP-Thin.ttf
# assets/google_fontsの中身
assets/google_fonts/
├── NotoSansJP-Black.ttf
├── NotoSansJP-Bold.ttf
├── NotoSansJP-ExtraBold.ttf
├── NotoSansJP-ExtraLight.ttf
├── NotoSansJP-Light.ttf
├── NotoSansJP-Medium.ttf
├── NotoSansJP-Regular.ttf
├── NotoSansJP-SemiBold.ttf
└── NotoSansJP-Thin.ttf
### pubspec.yaml
# アセットとして認識されるようにフォルダを追加
assets:
  - assets/google_fonts/

これでassets/google_fontsフォントファイルがあると、
そちらを使ってくれる。

このままだと、存在しないフォントの場合、ネットワークアクセスが発生するので、
GoogleFonts.configでフォントの取得を無効化しておく。

この例ではkDebugModeを使って、本番時のみ無効化している。

import 'package:flutter/foundation.dart';
import 'package:google_fonts/google_fonts.dart';

FutureOr<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // google fontsの設定
  GoogleFonts.config.allowRuntimeFetching = kDebugMode;

  // runApp
  runApp(const ProviderScope(child: App()));
}

フォントの読み込みを待つ

Webの場合、HTMLとCanvasKitの2つのレンダラーが用意されている。
デフォルトのCanvasKitだと、フォントが読み込まれるまで、
日本語が豆腐になってしまう。。

flutter run -d chrome --web-renderer htmlなどで、
HTML rendererを利用して解決する方法をよく見るけど、
CanvasKitでもなんとかうまくしたい。。

google_fontsにはfont swappingのために、
GoogleFonts.pendingFonts()がよういされているっぽい。

これを使って、runApp()の前にフォントを読み込むようにすると、
CanvasKitでも豆腐なく表示できるっぽい。

import 'package:google_fonts/google_fonts.dart';

FutureOr<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // google fontsの設定
  GoogleFonts.config.allowRuntimeFetching = kDebugMode;
  // Noto Sans JPの読み込みを待つ
  await GoogleFonts.pendingFonts([
      GoogleFonts.notoSansJpTextTheme(),
  ]);

  // runApp
  runApp(const ProviderScope(child: App()));
}

HTMLとCanvasKitの2つのレンダラーの違いは、

  • HTML renderer
    • HTML要素、CSSCanvasSVGの組み合わせを使用
    • ダウンロードサイズが小さい
  • CanvasKit renderer
    • Flutter mobileとdesktopと同等の見た目
    • Widget密度が高く、パフォーマンスが高速
    • ダウンロードサイズが大きい

初期表示の時間を優先する場合はHTML、
見た目やパフォーマンスが優先の場合はCanvasKit、
にするのが良さそう。


以上!! カスタムフォントも簡単に試したり、導入できたりするようになった(*´ω`*)