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の基礎文法を素早くインプットできる/