Flutter: ステータスバーの高さ「padding.top」を取得したが、値がゼロになってしまう

2022/8/7  Flutter エラー・バグ日記 

スマホ画面最上部の電池マークやWiFiマークのあるゾーン(ステータスバーと言うらしい)の高さを取得するため、

 

MediaQuery.of(context).padding.top

 

のプロパティにアクセスしたのだが、なぜか取得した値がゼロになる状況に陥った。

 

本記事はライトな日記思考で書いているので、詳細説明はしておらず、基本、テキストのみで画像とかはあまり載せておりません。。m(_ _)m

解説記事ではないため、解決していない内容や、その時々の間違った解釈を述べてしまっている可能性が大いにありますので、何卒、ご了承ください。

 

調べてみると、下記の情報があった。

 

 

若干、本件とは異なるケースの話だが、回答にある「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の学習で役立ったコンテンツ・書籍 /

 

 

 


Dart入門 – Dartの要点をつかむためのクイックツアー

タイトルとURLをコピーしました