AndroidのTypographyと格闘した話
本記事は株式会社ココナラ Advent Calendar 2024 21日目の記事です。
こんにちは。株式会社ココナラアプリ開発グループ Androidチームの藤永です。
大掃除の季節ですね。
ココナラのAndroidアプリにも過去の負債が色々と存在しており、様々な機能開発と並行して随時お掃除を進めています。
ココナラでは最近新しいデザインシステムに切り替える動きがあり、Typographyの刷新にあたって改めてAndroidのTypographyについて調査をしたので、今回はその内容をかいつまんでご紹介します。
Typographyとは
Typographyとは、HeadlineやBodyなどのように、文章の見た目を決めるための設定です。
文字サイズや行間などの様々な属性値を、サービス内やアプリ内であらかじめ定義することで統一的な見た目を提供できます。
ココナラAndroidアプリのデザイン実装のベースはMaterial 2であり、標準で定義されているTypographyは以下のURLで確認できます。
Line Heightについて
ココナラのデザインシステムの定義はFigmaで作成されています。
また、AndroidでのTypographyはTextStyleというクラスで表現されます。
問題となるのは行の高さを表現するLine Heightという値です。これはデザインツールのLine HeightとAndroidアプリのLine Heightが、それぞれのテキストのバウンディングボックス(以下bbox)へ与える影響が異なることに起因しています。
FigmaのLine Height
FigmaにおけるLine Heightは、単純に1行のテキストを内包するbboxの高さに一致します。
極端な例ですが、テキストサイズ14px
、Line Height 8px
と定義した場合、以下のようになります。
Android (Jetpack Compose) のLine Height
AndroidアプリにおけるLine HeightはBaseline間の距離であり、テキストのbboxの高さとは一致しません。
先ほどと同様に、テキストサイズ14px
、Line Height 8px
と定義した場合、以下のようになります。
(フォント自体や文字の太さ等は揃えていませんので、文字自体の見た目の差分は無視してください)
Androidのテキストのbboxは、内包するテキストが収まるように自動的に調節されます。基本的にはフォントが持つAscentとDescentの範囲を内包するように設定され、高さが大きい文字列であっても見切れないように更に追加でpaddingが自動的に確保されるようになっています。
何が問題になるのか
先ほどのテキストが2つのコンポーネントの間に存在し、上下に8dp
の余白が設定されているケースを考えます。
コンポーネント間の余白は、多くの場合、bboxの上下辺を起点として適用されるため、見た目に大きな差が生まれます。
一方で、bbox内の複数行の見た目は以下のように一致します。このことから、問題となるのは主に1行目上部と末尾行下部の余白であることがわかります。
自動設定されるpaddingの存在によって、AndroidとFigmaとの間では見た目の齟齬が生まれやすいです。余分なpaddingを削減するための属性値として、includeFontPadding
というものがあります。
includeFontPaddingとは
Androidの初期から存在する属性値で、デフォルトはtrueです。falseに設定することで前述のpaddingを削減することができます。
ただし、Typographyとは別でコンポーネントがもつ属性値のため、テキストを配置するたびに毎回この設定を記述する必要がありました。
Jetpack Composeではv1.2.0から、下位互換用のAPIとしてincludeFontPadding
が導入されました。デフォルト値はtrueで、Typographyごとに設定することができます。また、falseに設定すると、Line Heightをどのように扱うかを定義するLineHeightStyle
クラスと組み合わせて、より細かい制御をできるようになりました。
Compose UI v1.6.0-alpha01以降では、デフォルト値がfalseへ変更となりました。
実際に使用して比較すると英数字においては効果があるものの、日本語文字列においてはあまり効果がありませんでした。
ただし、実機で動作を確認したところ、Android 8までは効果があることがわかりました。この点は深堀りしていませんが、Android 9でフォールバックフォントの扱いが変わったためではないかと推測しています。
また、英数字においても結局のところAscent-Descent分の高さが確保される点は変わりません。
残るギャップについて
結局、(調査が足りていないという可能性はあるものの)includeFontPadding
によって余分なpaddingを削減するように設定しても、Figmaと同じ見た目を再現することはできないという結論に至りました。
デザインと実機の間のギャップを埋めるための方針として、大きく以下の3つが考えられます。
- デザインのTypography定義をAndroidで完全再現可能なものに更新する
- ギャップを許容する
- Figmaの見た目に合うように、実装箇所ごとにmargin、padding、offset等をその都度調整する
デザイナさんとも相談し、実現したいデザインと工数を鑑みて原則(2)で共通コンポーネントや重要な部分については(3)を検討する方針となりました。
まとめ
今回は、AndroidのTypographyについて、特にデザインツールとAndroidアプリの見た目の差が生じる問題について解説しました。
本当のところは「Android Viewだとまた別のパラメータもあって…」や「OSバージョンによってはこういう見た目になって…」などもあるのですが、今回は割愛しました。
AndroidアプリのTypographyについてはつい先日(2024/12/11)にリリースされた1.8.0-alpha07で新しいLineHeightStyle.Modeが登場するなど、直近でも進化が続いています。今後も動向を注視し、知見を深めていきたいと思います。
参考URL
- https://developer.android.com/develop/ui/compose/text/style-paragraph?hl=ja
- https://medium.com/androiddevelopers/fixing-font-padding-in-compose-text-768cd232425b
最後に
明日は@coco-ichiさんによる、 [2024年版]Baseline機能振り返り です。
ココナラでは積極的にエンジニアを採用しています。
採用情報はこちら。
カジュアル面談希望の方はこちら。
Discussion