Android 開発をしていると、端末のフォントサイズ設定を大きくしたらテキストが大きくなって UI がめちゃめちゃ崩れた…、みたいなことがあるかと思います。
XML レイアウトでは、TextView の textSize をあえて dp 指定することで端末のフォントサイズ設定を無視する方法がありました。
Jetpack Compose の場合はどうなのかと調べてみると、意外と簡単に無視できることがわかったので、備忘録として投稿します。
フォントサイズ設定はアクセシビリティにも関与するものなので、むやみに無視するのも好ましくないと考えます。
CompositionLocalProvider で LocalDensity を上書きし、fontScale を調整
LocalDensity.current.fontScale で現在のフォントサイズ設定が取得できます。
端末のフォントサイズのデフォルトは 1 で、設定を変更するとこの値が 1.15, 1.3, 1.5,... と変化することが確認できました。
CompositionLocalProvider を使い、LocalDensity を任意の Density で上書きすることで fontScale を調整することが可能です。
以下は fontScale を 1 に固定する例です。
CompositionLocalProvider(
LocalDensity provides Density(
LocalDensity.current.density, // そのまま
1F, // fontScaleを1に固定
),
) {
// この中のComposableはfontScaleが1で表示される
}
アプリ全体でフォントサイズ設定を無視したい場合は、アプリのルートでこの指定を書いておけば良さそうです。(注意点)
比較動画
fontScale をそのままにした場合と 1 に固定した場合で比較してみるとこのようになりました。
fontScale を 1 に固定した方では、フォントサイズを変更しているのに、テキストのサイズが変更されていないことが確認できます。(ステータスバーの文字は通常通り大きくなっています。)
| fontScale:そのまま | fontScale:1 に固定 |
|---|---|
![]() |
![]() |
注意点
観測した限り、Dialog コンポーザブルを使った場合、 Dialog の content 部分に関しては fontScale の上書きが無効になっているようでした。
そのため Dialog を使う場合は別途 content に対しても CompositionLocalProvider を使った上書き指定が必要になりそうです。
その他の方法
以下のような方法でも fontScale を無視させることができるようです。
スポットで無視するような場合には使い勝手がいいのかもしれません。
val TextUnit.nonScaledSp
@Composable
get() = (this.value / LocalDensity.current.fontScale).sp
Text(
text = "Hello Android!",
fontSize = 16.sp.nonScaledSp
)
参考

