要約
- Flutterでデバイス設定に応じたテキストサイズの調整
-
MediaQuery.textScalerを使えば簡単に対応できる - 高さの調整もスケール済みサイズで行うと違和感のないUIが作れる
はじめに
ユーザーが端末のアクセシビリティ設定でテキストサイズを変更すると、固定値でレイアウトを組んでいるアプリは簡単に崩れてしまいます。
本記事では、Flutter 3.16 以降で導入された TextScaler API を使って、高さをユーザーのテキストスケールに応じて計算する方法を紹介します。
アクセシビリティに配慮したアプリを作りたい方や、新しい MediaQuery.textScaler の使い方を知りたい方の参考になれば幸いです。
対象読者
- Flutter でアプリを開発している方
- アクセシビリティ対応やテキストスケーリングに興味のある方
- 従来の
textScaleFactorからTextScalerへの移行を検討している方
TextScalerとは
固定値でウィジェットの高さを決めている場合、ユーザーがデバイスのテキストサイズを大きくすると内容が収まらなくなります。Flutter では従来MediaQuery.textScaleFactorOf(context) でテキストの拡大倍率を取得し、フォントサイズに掛け算していました。しかし、Android 14 の非線形テキストスケーリング対応に伴い textScaleFactor は非推奨となり、新たに TextScaler が導入されました。
TextScaler は「テキスト内容をどのようにスケールするか」を表すクラスで、scale(double fontSize) メソッドを通じて元のフォントサイズからスケール後のサイズを計算します。非推奨の textScaleFactor と異なり、非線形スケールにも対応するため、Flutter 3.16 以降は MediaQuery.textScalerOf(context) から TextScaler を取得して scale を呼び出すのが推奨されています。
TextScaler と textScaleFactor の違い
textScaleFactor は単なる倍率であるため、フォントサイズ以外の高さや幅に掛け算するとユーザーのテキスト設定が反映されません。Flutter 3.16 以降では、TextScaler.scale() が計算する値を使って高さを調整することが推奨されます。たとえば、フォントサイズ 20 の効果的なスケール値を利用したい場合は次のようにします。
double effectiveScale = MediaQuery.textScalerOf(context).scale(20) / 20;
このように一度基準となるフォントサイズに対して scale() を呼び出し、その比率を他の寸法に適用すれば、ユーザーのテキスト設定に応じた非線形スケーリングにも対応できます。
非推奨となった textScaleFactor を高さなどの寸法にそのまま掛け算すると、Android 14 の非線形スケーリングに対応できず、UI が意図せず大きくなり過ぎたり小さくなり過ぎたりします。今後 textScaleFactor は削除予定であるため、TextScaler への移行を早めに進めましょう。
高さを動的に計算するコード例
例えば、ボタンの高さをデザイン上の基準値 57 にしたいとします。ユーザーがテキストサイズを変更しても押しやすい高さを保つために、以下のように TextScaler を使って高さを計算します。
class ScalableButton extends StatelessWidget {
final Widget child;
const ScalableButton({super.key, required this.child});
@Override
Widget build(BuildContext context) {
// MediaQuery から TextScaler を取得
final textScaler = MediaQuery.textScalerOf(context);
// 基準の高さ 57 にスケールを適用
final scaledHeight = textScaler.scale(57);
return SizedBox(
height: scaledHeight,
child: ElevatedButton(
onPressed: () {
// ボタン処理
},
child: child,
),
);
}
}
この 57 は、テキストサイズ設定がデフォルトのときに、1行のTextウィジェットの高さを基準として設計しています。
端末の設定で文字を大きくすると scaledHeight も自動的に大きくなるため、ボタン内のテキストが途切れたり重なったりする問題が解消されます。なお、非線形スケーリングは単純な掛け算ではなくTextScaler.scale() の戻り値に基づく計算が必要です。
実装例
TextScaler.scale() は主にフォントサイズを計算するための API であり、すべての寸法にそのまま当てはまるわけではありません。Flutter の公式ドキュメントでも「フォントサイズ以外の寸法をスケールするための一般的な規則は存在しない」と明記されており、必要に応じて UI を再設計することが推奨されています。高さをスケールする際は、要素内に表示する文字数やレイアウトの余白を考慮し、ユーザーにとって読みやすいかどうかを確認しましょう。
このように統一した計算方法を用意しておくと、端末設定によるテキストスケーリングに対応しやすくなり、アクセシビリティを意識したレイアウトが実現できます。
まとめ
- Flutter 3.16 以降では、ユーザーのテキスト設定に対応するために
TextScalerを使用することが推奨されます。 -
TextScaler.scale()を基準となる高さやフォントサイズに適用することで、端末のアクセシビリティ設定に応じたスケーリングが可能です。 - フォント以外の寸法をスケールする場合は UI を再設計することを検討し、実機での確認を怠らないようにしましょうx。