Flutter: AppBar上のアイコンサイズを縮小できず、サイズオーバーのエラーになる

※当サイトは、アフィリエイト広告を利用しています

結論:leadingWidth、titleSpacingを設定する 

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

 

「AppBar」の中に、思ったとおりの配置でアイコンを並べることができず、若干苦労した。

 

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

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

 

やりたかったのは、AppBarの中で、

 

  • ①左端に「leading:」属性でアイコンボタン(Backボタン)
  • ②中央に「title:」属性でテキスト入力欄(TextFormField)
  • ③右端に「title:」属性でアイコンボタン(メニューボタン)

 

を、①10%、②80%、③10%の横幅比率で設置すること。

 

あらかじめ、「MediaQuery.of(context).size.width」メソッドを使い、画面幅を取得しておき、①②③それぞれに、取得した画面幅から計算した横幅を「SizedBox」で指定し、「FittedBox」の「BoxFit.scaleDown」で横幅内に縮小されるようにした。

 

しかし、ビルドしてみると下図のような、サイズオーバーエラーが発生してしまった。。

 

 

A RenderFlex overflowed by 49 pixels on the right.

 

ちゃんと計算して幅を設定したのに、49pixelもオーバーしていると。。。

 

見てみると、「leading:」のボタンが全然小さくなってないし、「title:」に設定した「TextFormField」が、かなり右側からスタートしている。。

 

色々と「FittedBox」の設定方法などを変えてみるも、改善せず。。

 

仕方なく調べると、どうやらAppBarでは、「leading:」属性には幅が自動で設定され、「title:」属性には、自動でPaddingが入ってしまうらしく、これらを変更するには、

 

  • leadingWidth
  • titleSpacing

 

の設定が必要と判明。

 

こちらの記事に教えていただいた。

 

 

確かに、「AppBar」のソースコードを見ると、上記2つのプロパティ(属性)が存在していた。

 

そこで、「leadingWidth:」に、画面幅の10%の値を設定し、「titleSpacing:」には「0」を設定したところ、キレイに想定どおりの配置になった。

 

 

なお、「leadingWidth:」の設定により、Backボタンについては「SizedBox」の設置は不要にできた。

 

ただ、「FittedBox」の「BoxFit.scaleDown」は残しておかないと、アイコンが小さくならないので、下図のように「leadingWidth:」の幅によっては、「title:」属性のウィジェットで隠れてしまった(下図は、「leadingWidth:」を画面幅の5%にした場合の例)。

 

 

ご参考に、今回の例を記載したコードを掲載します(コピペすればそのまま実行いただけます)。

 

// クラス名、メソッド名、プロパティ名(変数名)について、筆者が作成したもの(名前変更可のもの)
// の名前の末尾には、大文字のオー「O」をつけています
// ※ライブラリ(パッケージ)で予め決められているもの(名前の変更不可のもの)と、
//  自分で作成したもの(名前の変更可のもの)の区別をしやすくするため

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Test",
      debugShowCheckedModeBanner: false,
      theme: ThemeData.light(),
      home: SampleScreenO(),
    );
  }
}

class SampleScreenO extends StatefulWidget {
  @override
  _SampleScreenOState createState() => _SampleScreenOState();
}

class _SampleScreenOState extends State<SampleScreenO> {
  @override
  Widget build(BuildContext context) {

    double screenWidthO = MediaQuery.of(context).size.width;

    return  Scaffold(
      appBar: AppBar(

        // 以下の2つが無いと、サイズオーバーのエラーになる
        leadingWidth: screenWidthO * 0.1,
        titleSpacing: 0.0,

        leading: SizedBox(  // leadingWidth を設置していれば、この SizedBox は不要
          width: screenWidthO * 0.1,
          child: FittedBox(
            fit: BoxFit.scaleDown,
            child: IconButton(
              icon: Icon(Icons.arrow_back_outlined),
              onPressed: () {},
            ),
          ),
        ),

        title: Row(
          children: [
            SizedBox(
              width: screenWidthO * 0.8,
                child: TextFormField(
                  decoration: InputDecoration(
                    border: InputBorder.none,
                    filled: true,
                    fillColor: Theme.of(context).primaryColorLight,
                  ),
                ),
            ),
            SizedBox(
              width: screenWidthO * 0.1,
              child: FittedBox(
                fit: BoxFit.scaleDown,
                child: IconButton(
                  icon: Icon(Icons.menu),
                  onPressed: () {},
                ),
              ),
            ),
          ],
        ),
      ),

      body: Container(),
    );
  }
}

 

 

\一般的なエラー対処法をまとめた記事はこちら/

 

リリースしたアプリ(全てFlutterで開発)

 

個人アプリ開発で役立ったもの

おすすめの学習教材

超初心者向けでオススメな元Udemyの講座/

 

 \キャンペーン時を狙えば安価で網羅的な内容が学べる(日本語訳あり)/

 

\Gitの基礎について無料で学べる/

 

おすすめの学習書籍

実用的image_pickerに関してかなり助けられた/

 

Dartの基礎文法を素早くインプットできる/


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

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