MediaQueryは、現在のメディア環境(画面サイズ、デバイスの向き、ピクセル密度、システムの余白、フォントサイズ)に関する情報を提供するFlutterのオブジェクトです。MediaQueryDataはこれらすべてのメトリクスのコンテナであり、MediaQuery.of(context)を介してアクセスできます。公式のFlutterドキュメント(2026年)によると、MediaQueryはアダプティブデザインの基盤です。これを使用して、モバイルレイアウトとタブレットレイアウトのどちらを表示するかを決定し、セーフエリアの余白を計算し、画面に応じて要素のサイズを選択します。
重要なポイント
MediaQueryは、アプリケーションのメディア環境に関するデータを提供するFlutterのウィジェットおよびクラスです。MediaQueryはアプリケーション全体をルートのMaterialAppまたはCupertinoAppウィジェットでラップし、子ウィジェットはMediaQuery.of(context)を介してこのデータにアクセスできます。
Flutterがアプリケーションを起動すると、現在のデバイスのすべてのメトリクスを含むMediaQueryDataのインスタンスを作成します。このデータは、デバイスの回転、ウィンドウサイズの変更(デスクトップ)、キーボードの表示、システムのアクセシビリティ設定の変更など、変化に応じて自動的に更新されます。MediaQueryはデータの変更時にウィジェットサブツリーを再構築し、リアクティブなインターフェース適応を提供します。
MediaQueryDataには以下が含まれます:size(画面サイズ)、devicePixelRatio(ピクセル密度)、textScaleFactor(システム設定からのフォントスケール)、viewInsets(キーボードで覆われた領域)、viewPadding(システムの余白)、orientation(向き)、platformBrightness(ライトテーマまたはダークテーマ)。
まとめ:MediaQueryはFlutterにおけるデバイス情報の中心的なソースです。MediaQuery.of(context)へのアクセスは、レスポンシブインターフェースを構築するための最初のステップです。
MediaQueryDataには多数のプロパティがありますが、最もよく使用されるのはレイアウト構築に影響するものです。主要なものを見てみましょう。
MediaQuery.of(context).sizeは、デバイス非依存ピクセル(dip)での画面の幅と高さを持つSizeオブジェクトを返します。これらの値はシステムの余白を考慮しません。レスポンシブレイアウトの計算では、sizeが主要なメトリクスであり、モバイル、タブレット、デスクトップのレイアウトのブレークポイントを決定します。
ViewPaddingは、システムがステータスバー、ノッチ(画面の切り欠き)、システムナビゲーションパネル、ホームインジケーター(iOS)のために確保する余白です。これらの余白を考慮しないと、コンテンツがシステム要素の下に表示される可能性があります。MediaQuery.of(context).paddingは、ページのルートコンテナにパディングとして適用する必要があるEdgeInsetsを返します。
ViewInsetsは、ソフトウェアキーボードで覆われた画面領域です。入力フィールドでは、コンテンツをキーボードの上に持ち上げるためにviewInsets.bottomを監視することが重要です。Flutterはscaffoldでこれを自動的に処理しますが、カスタムレイアウトではMediaQuery.of(context).viewInsetsを直接使用する必要があります。
Orientation — 縦方向(portrait)または横方向(landscape)の向き。幅と高さを比較して決定されます:幅が高さより小さい場合はportrait、それ以外はlandscapeです。本番コードでは、向きを使用して要素の縦横の配置を切り替えます。
まとめ:4つの主要プロパティ(size、viewPadding、viewInsets、orientation)でレスポンシブデザインタスクの90%をカバーできます。残りのプロパティ(textScaleFactor、platformBrightness、devicePixelRatio)は特定のシナリオで使用されます。
MediaQueryはFlutterにおけるレスポンシブデザインの基盤です。これを使用してブレークポイントを決定し、画面サイズに応じてレイアウトを切り替え、さまざまなデバイスに合わせて余白を調整します。
典型的なシナリオ:モバイルアプリが製品リストを表示する必要がある場合。電話(幅 < 600dp)では1列、タブレット(幅 600–900dp)では2列、デスクトップ(幅 > 900dp)では3列です。MediaQuery.of(context).size.widthを使用すると、フォームファクターごとに別々の画面を用意しなくても、動的に列数を選択できます。
2つ目のシナリオ:最新デバイスでのシステムジェスチャーインセットの考慮。Dynamic Island搭載のiPhoneやジェスチャーナビゲーションのAndroidでは、システムの余白が画面の一部を消費します。MediaQuery.of(context).paddingは各デバイスタイプの正しい値を返し、Scaffoldはbodyを介して自動的に適用します。カスタムウィジェットでは、MediaQueryからパディングを明示的に渡す必要があります。
3つ目のシナリオ:システムのアクセシビリティ設定への適応。MediaQuery.of(context).textScaleFactorは、ユーザーが設定でフォントサイズをどの程度拡大したかを示します。textScaleFactor > 1.3では、長いテキストがカードの境界を超えてレイアウトが崩れる可能性があります。レスポンシブレイアウトはこれを考慮し、必要に応じてよりシンプルなレイアウトに切り替える必要があります。
まとめ:MediaQueryは単なるメトリクスのソースではなく、真にレスポンシブなインターフェースを構築するためのツールです。ブレークポイント、セーフエリア、アクセシビリティの考慮事項に使用してください。
例1は、画面サイズを取得し、ブレークポイントを適用して列数を選択する方法を示しています。
int getColumnCount(BuildContext context) {
final width = MediaQuery.of(context).size.width;
if (width > 900) return 3;
if (width > 600) return 2;
return 1;
}
上記の例は、画面幅に基づいて列数を選択する関数を示しています。ブレークポイント600と900は、電話、タブレット、デスクトップの一般的に受け入れられているMaterial Design標準に対応しています。
例2 — システムの余白を考慮した正しいコンテンツ配置のための、viewPaddingを使用したMediaQueryの使用。
Widget build(BuildContext context) {
final padding = MediaQuery.of(context).padding;
return Padding(
padding: EdgeInsets.only(
top: padding.top,
left: padding.left,
right: padding.right,
),
child: const MyContent(),
);
}
この例では、paddingがシステムの余白を使用してコンテンツをPaddingでラップしています。topはステータスバーとノッチを考慮し、left/rightはセーフエリアを考慮します。Scaffoldが通常下部ナビゲーションを処理するため、bottomは含まれていません。
例3 — 向きの決定と要素配置の切り替え。
Widget build(BuildContext context) {
final isPortrait = MediaQuery.of(context).orientation == Orientation.portrait;
return isPortrait
? const Column(
children: [HeaderBanner(), ContentList()],
)
: const Row(
children: [HeaderBanner(), ContentList()],
);
}
縦方向モードでは要素が縦に(Column)配置され、横方向モードでは横に(Row)配置されます。このアプローチにより、デバイスを回転させたときにスペースを最大限に活用できます。
まとめ:MediaQueryはレスポンシブレイアウトを構築するための主要なツールです。Flutterインターフェースを開発する際は、常にシステムの余白、ブレークポイント、向きを考慮してください。
間違い1:MediaQueryが設定されていないコンテキストでMediaQuery.of(context)を呼び出す。ウィジェットがツリー内でMediaQueryより上にある場合、呼び出しは実行時エラーを引き起こします。解決策:MediaQueryがルートウィジェットとして設定されているMaterialAppまたはCupertinoAppでラップされたウィジェット内で常にMediaQuery.of(context)を呼び出してください。
間違い2:セーフエリアを忘れる。開発者はシステムの余白を考慮せずに要素を配置するためにMediaQuery.sizeを使用します。ノッチやジェスチャーナビゲーションのあるデバイスでは、コンテンツがステータスバーの下に表示されます。解決策:位置座標からMediaQuery.of(context).paddingを差し引いてください。
間違い3:サイズへの固定結合。MediaQuery.of(context).size.widthを使用して要素の正確なサイズを設定する(width: size.width * 0.3)と、同じフォームファクターのデバイスでのみ機能します。デスクトップやタブレットでは、レイアウトが不自然に見えます。解決策:固定のパーセンテージではなく、ExpandedやFlexibleと組み合わせてブレークポイントを使用し、柔軟なレイアウトにしてください。
間違い4:textScaleFactorを無視する。ユーザーがシステムフォントを拡大すると、テキストがコンテナの境界を超えてインターフェースが崩れる可能性があります。解決策:MediaQuery.of(context).textScaleFactorを確認し、1.3を超える値ではスクロール可能なシンプルなレイアウトに切り替えてください。
まとめ:MediaQueryは強力ですが繊細なツールです。すべてのデバイスでインターフェースが正しく表示されるように、システムの余白、向き、アクセシビリティ設定を考慮してください。
よくある質問
MediaQuery.sizeは、論理ピクセルでの画面またはアプリケーションウィンドウの合計サイズです。MediaQuery.viewInsetsは、システムキーボードで覆われた領域です。キーボードなしの利用可能なスペースを計算するには:size.height - viewInsets.bottom。
LayoutBuilderは、画面全体ではなく親コンテナの寸法を提供します。ウィジェットのサイズが特定の親内の利用可能なスペースに依存する場合はLayoutBuilderを、グローバルな画面メトリクスが必要な場合はMediaQueryを使用してください。
自動的に。デバイスが回転すると、FlutterはMediaQueryDataを更新し、サブツリーを再構築します。orientationプロパティが変更され、すべての購読ウィジェットのビルダーが新しいデータで呼び出されます。
はい。MediaQuery.removePadding、MediaQuery.removeViewInsets、または別のDataを持つMediaQueryを使用して、上書きされたデータでウィジェットの一部をMediaQueryでラップします。これはiframeへの埋め込みやプレビューモードで使用されます。
テスト用に、Flutterはテスト環境でsetScreenSizeとMediaQueryラッパーを提供しています。ウィジェットテストでは、テスト対象のコンポーネントをMaterialAppまたはテストデータを含むMediaQueryでラップして、画面寸法を制御します。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。