Jetpack Compose で autoSizeText を実装する
Jetpack Compose における autoSizeText は、Jetpack Compose Roadmap では現在 In Focus となっていますが、 TextMeasurer
を用いることで実装可能です。
やりたいこと
- テキストのフォントサイズをレイアウトに合わせて調整する
- 表示・パフォーマンスも気にする
環境
- Kotlin: 1.9.21
- Compose Compiler: 1.5.6
- Compose BoM: 2023.10.01
まずはナイーブに実装してみる
単純には、フォントサイズを remember しておいて、適宜調整すれば表示はできそうです。
しかし実際に実装してみると、以下のようにアニメーションしているように表示されます。
また Recomposition もフォントサイズが変わるたびに発生します。
今回のケースでは表示ボタンを押してから表示が止まるまでに 170 回以上も Recomposition が走っていました。
表示・パフォーマンスも気にして実装する
上記の問題を解決するには、表示前に一気にフォントサイズを求めてあげる必要があります。
JetpackCompose において、テキストを実際に表示することなくレイアウトの計算を行うのに TextMeasurer
を使うことができます。
TextMeasurer
は rememberTextMeasurer()
で取得でき、measure()
でレイアウト計算に用いる TextLayoutResult
を取得できます。
最適なフォントサイズを求める際、先の実装のように順に確かめるよりも TextView
で実装されている ように二分探索でやるとより高速に処理できます。
measure()
には layout
Modifier でおなじみの Constraints
が必要となりますが、BoxWithConstraints
を使うことで簡単に取得できます。
ナイーブな実装との比較は以下のようになり、即座に表示が完了するほか、Recomposition も発生していませんでした。
おわりに
TextMeasurer
を使うことで Recomposition を繰り返すことなく最適なフォントサイズを求めることができました。
measure()
は他にも Text
composable の引数にあるような設定値を受け取るため、より細かい指定も可能です。
コード全体は以下から確認できます。
Discussion