Flutter: AppBar上のアイコンサイズを縮小できず、サイズオーバーのエラーになる
結論:leadingWidth、titleSpacingを設定する
2022/8/1 Flutter エラー・バグ日記
「AppBar」の中に、思ったとおりの配置でアイコンを並べることができず、若干苦労した。
やりたかったのは、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の基礎文法を素早くインプットできる/






