🐫

Flutterで英数字と日本語で別々のフォントを利用する

2023/12/19に公開

flutterで英数字のみの欧文フォントで表示し、日本語は別の和文フォントを適用する方法です。

はじめに

想定する読者

🙆‍♂️: flutter でこれからフォントを指定しようとしている人。
🙆‍♂️: 使いたいフォントが英数字のみ対応していて、日本語だけ別のフォントを適用したい人。
🙅‍♀️: Noto Sans や Murecho といった日本語に対応したフォントを利用する人。

前提知識

公式docs:
https://docs.flutter.dev/cookbook/design/fonts
素晴らしいカスタムフォント導入の記事:
https://zenn.dev/flutteruniv_dev/articles/20220419-143426-flutter-custom-fonts

本文

イケてる英数字フォントを使いたい

みなさん、「Montserrat」ってフォントをご存知でしょうか?元々いい感じのゴシックフォントで「Gotham」というフォントがあるのですが、有料なので手が出しにくい背景があります。そんなGothamと同じようなフォント感でしかも「無料」[1]で利用できるフォントがあります!それが「Montserrat」です。

https://tackweb.net/index.php/2019/09/11/gotham_montserrat/

早速使ってみましょう!#前提知識で紹介した「素晴らしいカスタムフォント導入の記事」のサンプリコードがありがたいことに公開頂いているので、コードをcloneしてきます。
https://github.com/susatthi/flutter-sample-fonts

Montserratだけ適用してみる

Montserratを使ってみましょう! Google Fonts からダウンロードして、上記コードに適用します。
https://fonts.google.com/specimen/Montserrat
適用した結果(Android):

適用前(Roboto) 適用後(英数字のみMontserrat)
適用前(Roboto) 英数字のみMontserrat

ちゃんと英数字はイケてる感じになりましたが、欧文フォントなので和文非対応です。日本語表示が良くないですね。何もしないと、非対応の文字は端末依存のデフォルトフォントが適用されます。この場合「Roboto」が適用されており、中華風に表示されています。

日本語用の和文フォントを設定する

次に、日本語にあてるフォントの設定をしましょう。web開発を参考にすると、CSSのfont-familyは複数のフォントを指定可能[2]なはずです。しかし、ThemeDatafontFamilyプロパティはリストを受け取らないので、複数指定は難しそうです。CSSと同じように、優先度順でフォントを指定する方法がないか探してみます。

ThemeDataの実装を見ていくと、fontFamilyFallbackというプロパティが用意されていました。
https://api.flutter.dev/flutter/painting/StrutStyle/fontFamilyFallback.html
探していた「優先度順でフォントを指定する」という期待通りのプロパティですね!ゴシック体かつ複数weightが用意されている和文フォントとして、「Noto Sans Japanese」を日本語表示に採用します。適用結果は以下の通りです。

fallbackなし fallbackあり(NotoSansJP)
fallbackなし fallbackあり

英数字は Montserrat で表示され、日本語は NotoSansJP で表示されていて、いい感じです🎵

今回のサンプルコード

すささんのサンプルコードをforkして、fallback用のフォントを指定できるようにしました。コード差分は以下になります。
https://github.com/ken-ty/flutter-sample-fonts/pull/1


蛇足

google_fontsパッケージを使いたい

記事を書くにあたり、 google_fonts パッケージをちゃんとみてみたらHTTP経由せずにフォント読み込みできるってことを知りました。今回同様に Google Fonts のサイトからフォントファイルをダウンロードすると、assetsにたくさん定義しなくても一致するフォントがダウンロードされているか確認してくれるそうです。Theme化やEnum化も用意されているものを使えて便利そうです。フォントの管理にはこちらのパッケージを利用するのが良さそうです。
https://pub.dev/packages/google_fonts

Font bundling in assets. Matching font files found in assets are prioritized over HTTP fetching. Useful for offline-first apps.

font-family設定のCSSサンプル

WEB開発の文脈で出てくるCSSサンプルです。
中略2でも触れたので紹介します。

// 英数字はMontserratが適用され, それ以外はメイリオが適用される.
// もしwebフォントを読み込めなかったら、クライアントのsans-serifの適当なフォントが適用される.
// 記述ルールとして, フォントファミリーは引用符で囲い, 総称フォント名は囲わない

font-family: "Montserrat", "メイリオ", sans-serif;

https://developer.mozilla.org/ja/docs/Web/CSS/font-family

優先度で表示分けできないケース

英数字表示にフォントA(日本語対応している)、 日本語表示にフォントB(日本語対応している)を適用するケースってどうするんでしょうね?webフロントエンド開発でもモバイル開発でも経験ないですが、ケースとして発生したら試してみたいですね。誰かやってみたら教えてください。

脚注
  1. もちろん、フォントの開発者に敬意を払って利用しましょう。ライセンスには遵守してください。 ↩︎

  2. CSSのfont-familyプロパティは複数のプロパティ指定に対応しており、前に設定したフォントから順に優先されて適用されます。なので、英数字に優先して利用したいフォントを先に指定し、日本語用のフォントはその次に指定すれば良いです。 ↩︎

Flutter大学

Discussion