🙄
[Flutter] 『SingleChildScrollView & Column』の代わりに『ListView』を使っていた時の失敗談
Flutterで『SingleChildScrollView & Column』の代わりに『ListView』を使っていた時の失敗談(?)を書いておきます。なお、個人開発での話です。
アホなミスなので、どうぞ嘲笑ってください。
どこでListViewを代わりに使っていたか
私の場合、Formの部品設置をListViewで行っていました。
コードは以下のような感じです。
return Form(
key: _formKey,
child: ListView(
children: [
TextFormField(
controller: _nameController,
validator: (name) {
if (name == null || name.isEmpty) {
return '名前を入力してください。';
}
return null;
},
),
// 以下にも複数のForm部品が設置されている
ElevatedButton(
onPressed: () {
// 送信処理
},
child: Text('送信'),
),
],
),
);
このように、普通はSingleChildScrollViewとColumnを使うような場面でもListViewを使用していました。
なぜ代わりにListViewを使っていたか
こちらの理由は単純で、『同じ見た目動作で、コードのネストを浅くできるから』です。
以下2つのコードは見た目的には同じになりますよね。
return SingleChildScrollView(
child: Column(
children: List.generate(20, (i) {
return ListTile(
title: Text('$i'),
);
}),
),
);
return ListView(
children: List.generate(20, (i) {
return ListTile(
title: Text('$i'),
);
}),
);
「ListViewを使えばネストを浅くできるし、まぁこれでいっか!」という感じで使っていました。
どこでミスをしたか
私の場合、先程のFormのvalidatorが反応しない事象が発生しました。
これはなぜかというと、『ListViewは、スクロールされることによって表示されなくなった子Widgetを破棄するから』です。
適当な画像ですが、以下のような感じです。
送信ボタンが一番下にあるため、スクロールによって上に設置した部品Widgetが破棄されてしまい、validatorが反応しなかったわけです。
ListViewをSingleChildScrollViewとColumnに直したらvalidatorはしっかり反応しました。
まとめ
『SingleChildScrollView & Column』の代わりに『ListView』を使用するのはやめましょう。
各Widgetは適材適所の場所に配置しましょう。
Discussion