Flutter の GridView を使って、正方形のサムネイルを表示するアプリを作っています。複数選択することはできたのですが、タップする度にすべて再描画されてしまい画面が点滅してしまいます。
問題を解決することができたので紹介します。

ソースコード
multi_select_gridview.dart
import 'package:flutter/material.dart';
class MultiSelectScreen extends StatefulWidget {
@override
_MultiSelectState createState() => _MultiSelectState();
}
class _MultiSelectState extends State<MultiSelectScreen> {
List<String> list = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T'];
List<bool> selectList = new List.filled(20, false);
@override
Widget build(BuildContext context) {
return Scaffold(
body: GridView.extent(
maxCrossAxisExtent: 150,
children: List.generate(20, (index) {
return MultiSelectItem(
name: list[index],
selectList: selectList,
index:index);
})),
);}
}
/// isSelected で再描画を行い、selectList を親に参照させることで、
/// すべてが再描画されることを防ぎます。
class MultiSelectItem extends StatefulWidget {
MultiSelectItem({
@required this.name,
@required this.selectList,
@required this.index,
});
String name;
List<bool> selectList;
int index;
bool isSelected = false;
@override
_MultiSelectItemState createState() => _MultiSelectItemState();
}
class _MultiSelectItemState extends State<MultiSelectItem> {
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(2),
child: GestureDetector(
onTap: () {
setState((){
widget.isSelected = !widget.isSelected;
widget.selectList[widget.index] = widget.isSelected;
});
},
child: Stack(children: <Widget>[
Container(color: Colors.grey),
Center(child: Text(widget.name, style: TextStyle(fontSize: 30,))),
Positioned(
right: 6.0, bottom: 6.0,
child: CircleAvatar(
backgroundColor: widget.isSelected ? Colors.black38 : Color(0x00000000),
child: Icon( widget.isSelected ? Icons.check : null,
size: 36,
color: Colors.lightBlue
))),
]),
),);}
}
解説
複数選択するために List< bool> を使い setState() を実行します。すると GridView 全体が再描画されて画面が点滅したようになってしまいます。
そこで GridView の個々のアイテムを StatefulWidget にします。アイテムには、自身の isSelected と 親を参照する selectList の2つを持たせるのがポイントです。タップすると自身の isSelected だけが再描画されます。selectList も変更しますが再描画には影響しません。
まとめ
GlidView で選択する度に、画面がすべて再描画されてしまう問題の解決法を紹介しました。Flutter 初心者です。今回の解決法を調べるためにいくつものサンプルを試しました。setState() についてや、StatefulWidget と StatelessWidget の違いなど、急がば回れでかなり勉強になりました。