Flutter: ステータスバーの高さ「padding.top」を取得したが、値がゼロになってしまう
結論:contextを引数で渡すか、起動時にpadding.topを取得しておく
2022/8/7 Flutter エラー・バグ日記
スマホ画面最上部の電池マークやWiFiマークのあるゾーン(ステータスバーと言うらしい)の高さを取得するため、
MediaQuery.of(context).padding.top
のプロパティにアクセスしたのだが、なぜか取得した値がゼロになる状況に陥った。
調べてみると、下記の情報があった。
若干、本件とは異なるケースの話だが、回答にある「contextのpaddingがゼロ」のウィジェットに対して実行しているから、というコメントで気がついた。
自分のコードでは、「Column」で並べたウィジェットのうち、一部のウィジェットを別クラス(Stateless Widget)に飛ばし、その別クラス内で、「padding.top」を取得しようとしていた。
最初の画面全体のビルドを担う「build」メソッドが持つ「context」は、画面上部の「padding」=「ステータスバーの高さ」を認識しているが、別クラスに飛んだ先のウィジェットのビルドを担う「build」メソッドが持つ「context」には、画面全体のpadding情報が無いため、ゼロになる、ということだと思われる。
確かに、画面全体のビルドを担う「build」メソッドが持つ「context」を、別クラスに引数として渡し、渡された「context」を使って「padding.top」にアクセスしたら、ステータスバーの値を取得できた。
画面横幅を取得する「MediaQuery.of(context).size.width」や、画面縦幅を取得する「MediaQuery.of(context).size.height」では、こういう問題は生じないのだが(contextを渡さずに、別クラスに飛んだ先で値を取得できる)、「padding.top」は事情が違うらしい。
上記のことを検証するため、下記サンプルコードを作成して確かめてみた。
「context」を引数として渡さないウィジェットでは、「padding.top」が取得できず、渡したウィジェットでは取得できていることが分かる。

// クラス名、メソッド名、プロパティ名(変数名)について、筆者が作成したもの(名前変更可のもの)
// の名前の末尾には、大文字のオー「O」をつけています
// ※ライブラリ(パッケージ)で予め決められているもの(名前の変更不可のもの)と、
// 自分で作成したもの(名前の変更可のもの)の区別をしやすくするため
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "Test",
theme: ThemeData.light(),
home: SampleScreenO(),
);
}
}
class SampleScreenO extends StatefulWidget {
@override
_SampleScreenOState createState() => _SampleScreenOState();
}
class _SampleScreenOState extends State<SampleScreenO> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
height: 50,
color: Colors.blue,
child: Text("ステータスバーの高さ ${MediaQuery.of(context).padding.top}"),
),
Container(
height: 50,
color: Colors.lightBlue,
child: Text("画面の縦幅 ${MediaQuery.of(context).size.height}"),
),
/// contextを引き継がないウィジェット
TestWidgetO(),
/// contextを引き継ぐウィジェット
AnotherTestWidgetO(contextO: context),
],
),
);
}
}
/// contextを引き継がないウィジェット
class TestWidgetO extends StatelessWidget {
const TestWidgetO({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
height: 50,
color: Colors.green,
child: Text("ステータスバーの高さ ${MediaQuery.of(context).padding.top}"),
),
Container(
height: 50,
color: Colors.lightGreen,
child: Text("画面の縦幅 ${MediaQuery.of(context).size.height}"),
),
],
);
}
}
/// contextを引き継ぐウィジェット
class AnotherTestWidgetO extends StatelessWidget {
final BuildContext contextO;
const AnotherTestWidgetO({
Key? key,
required this.contextO,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
height: 50,
color: Colors.yellow,
// 引き継いだ「contextO」を用いて「padding.top」にアクセス
child: Text("ステータスバーの高さ ${MediaQuery.of(contextO).padding.top}"),
),
Container(
height: 50,
color: Colors.limeAccent,
child: Text("画面の縦幅 ${MediaQuery.of(context).size.height}"),
),
],
);
}
}
実用面では、「context」を渡していくのは面倒なので、アプリ起動時に「padding.top」にアクセスし、定数に代入しておくのが良さそうだと思った。
\一般的なエラー対処法をまとめた記事はこちら/
リリースしたアプリ(全てFlutterで開発)
個人アプリ開発で役立ったもの
おすすめの学習教材
\超初心者向けでオススメな元Udemyの講座/
\キャンペーン時を狙えば安価で網羅的な内容が学べる(日本語訳あり)/
\Gitの基礎について無料で学べる/
おすすめの学習書籍
\実用的。image_pickerに関してかなり助けられた/
\Dartの基礎文法を素早くインプットできる/





