🍜
Flutter MediaQuery.removePaddingによってviewPaddingが0になる
Overlay Widgetを使ってWidgetツリーを飛び越えて表示した時に、viewPaddingの値が想定と違い混乱することがありました。これはMediaQuery.removePaddingが適用されたWidgetツリーの内側と外側で、viewPaddingの値が異なることが原因でした。
この記事では、MediaQuery.removePaddingの使い方と、viewPaddingの値が変わる理由を解説します。
MediaQuery.removePadding
MediaQuery.removePaddingメソッドは、指定したパディングを0に置き換えたMediaQueryDataを作成します。
これは、AppBarやSafeAreaといったWidgetの内部で使われています。
AppBarは、removeBottom: trueによって、画面下のパディングが0に指定されています。
SafeAreaは、パラメータで指定した位置のパディングが0に指定されていますね。
SafeAreaのパディングを削除するパラメータはデフォルトでtrueです。
例えば、以下のコードだと画面の左・右・上のパディングが0になります。
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return SafeArea(top: false, child: Text('テスト'));
}
}
MediaQuery.viewPaddingの値が変わる
removePaddingによってviewPaddingの値が変わることを見てみましょう。
以下はAppBarとMediaQuery.removePaddingを順番に適用したコードです。
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(home: _ViewPaddingWidget()));
}
class _ViewPaddingWidget extends StatelessWidget {
@override
Widget build(BuildContext contextX) {
return Scaffold(
// removeTop: true,
appBar: AppBar(title: Text('AppBar')),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// EdgeInsets.fromLTRB(left, top, right, bottom)
Text('contextX: ${MediaQuery.viewPaddingOf(contextX)}'),
Builder(
builder:
(contextY) => Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('contextY: ${MediaQuery.viewPaddingOf(contextY)}'),
MediaQuery.removePadding(
context: contextY,
removeBottom: true,
child: Builder(
builder:
(contextZ) => Text(
'contextZ: ${MediaQuery.viewPaddingOf(contextZ)}',
),
),
),
],
),
),
],
),
);
}
}
このコードを実行すると、contextX、contextY、contextZの順にパディングが無くなっていることが確認できます。
以下はiPhone Xsで実行した結果です。上下にviewPaddingが設定された後、上パディングがなくなり、下パディングがなくなっています。

まとめ
-
MediaQuery.removePaddingによって、MediaQuery.viewPaddingの値が変わる -
MediaQuery.removePaddingは、AppBarやSafeAreaの内部で使われている -
MediaQuery.removePaddingは、指定したパディングを0に置き換えたMediaQueryDataを作成する
参考文献
Discussion