Flutterで英数字と日本語で別々のフォントを利用する
flutterで英数字のみの欧文フォントで表示し、日本語は別の和文フォントを適用する方法です。
はじめに
想定する読者
🙆♂️: flutter でこれからフォントを指定しようとしている人。
🙆♂️: 使いたいフォントが英数字のみ対応していて、日本語だけ別のフォントを適用したい人。
🙅♀️: Noto Sans や Murecho といった日本語に対応したフォントを利用する人。
前提知識
公式docs:
素晴らしいカスタムフォント導入の記事:本文
イケてる英数字フォントを使いたい
みなさん、「Montserrat」ってフォントをご存知でしょうか?元々いい感じのゴシックフォントで「Gotham」というフォントがあるのですが、有料なので手が出しにくい背景があります。そんなGothamと同じようなフォント感でしかも「無料」[1]で利用できるフォントがあります!それが「Montserrat」です。
早速使ってみましょう!#前提知識で紹介した「素晴らしいカスタムフォント導入の記事」のサンプリコードがありがたいことに公開頂いているので、コードをcloneしてきます。
Montserratだけ適用してみる
Montserratを使ってみましょう! Google Fonts からダウンロードして、上記コードに適用します。
適用した結果(Android):適用前(Roboto) | 適用後(英数字のみMontserrat) |
---|---|
ちゃんと英数字はイケてる感じになりましたが、欧文フォントなので和文非対応です。日本語表示が良くないですね。何もしないと、非対応の文字は端末依存のデフォルトフォントが適用されます。この場合「Roboto」が適用されており、中華風に表示されています。
日本語用の和文フォントを設定する
次に、日本語にあてるフォントの設定をしましょう。web開発を参考にすると、CSSのfont-familyは複数のフォントを指定可能[2]なはずです。しかし、ThemeData
のfontFamily
プロパティはリストを受け取らないので、複数指定は難しそうです。CSSと同じように、優先度順でフォントを指定する方法がないか探してみます。
ThemeData
の実装を見ていくと、fontFamilyFallback
というプロパティが用意されていました。
探していた「優先度順でフォントを指定する」という期待通りのプロパティですね!ゴシック体かつ複数weightが用意されている和文フォントとして、「Noto Sans Japanese」を日本語表示に採用します。適用結果は以下の通りです。
fallbackなし | fallbackあり(NotoSansJP) |
---|---|
英数字は Montserrat で表示され、日本語は NotoSansJP で表示されていて、いい感じです🎵
今回のサンプルコード
すささんのサンプルコードをforkして、fallback用のフォントを指定できるようにしました。コード差分は以下になります。
蛇足
google_fontsパッケージを使いたい
記事を書くにあたり、 google_fonts パッケージをちゃんとみてみたらHTTP経由せずにフォント読み込みできるってことを知りました。今回同様に Google Fonts のサイトからフォントファイルをダウンロードすると、assetsにたくさん定義しなくても一致するフォントがダウンロードされているか確認してくれるそうです。Theme化やEnum化も用意されているものを使えて便利そうです。フォントの管理にはこちらのパッケージを利用するのが良さそうです。
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;
優先度で表示分けできないケース
英数字表示にフォントA(日本語対応している)、 日本語表示にフォントB(日本語対応している)を適用するケースってどうするんでしょうね?webフロントエンド開発でもモバイル開発でも経験ないですが、ケースとして発生したら試してみたいですね。誰かやってみたら教えてください。
Discussion