概要
公式のSliverGridの動画に出てくる↓を、画像を展開するグリッドとして実装します。動的なコンテンツ表示でよく使うやつですね。
雑にググったら色付きのタイルを並べてるサンプルは出てくるけど画像を動的に並べるコードがあんまり出てこなかったので書きました。
前提となるウィジェット
Scaffoldと、Sliverを使う時のお約束であるCustomScrolView
を置きます。
Scaffold(
body: CustomScrolView()
)
画面はまだ真っ白です。
公式の仰せのままにとりあえずSliverGridを置く
色々すっ飛ばしてる気もしますが、一旦公式のサンプルをそのままコピペします。
Scaffold(
body: CustomScrollView(
slivers: <Widget>[
SliverGrid(
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 200.0,
mainAxisSpacing: 10.0,
crossAxisSpacing: 10.0,
childAspectRatio: 4.0,
),
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Container(
alignment: Alignment.center,
color: Colors.teal[100 * (index % 9)],
child: Text('grid item $index'),
);
},
childCount: 20,
),
),
]
)
画面ができました。
1行解説
このままでは解説になってないので使ってるプロパティを雑に訳してみます。
-
gridDelegate
- グリッドのサイズ自体をコントロールするウィジェット。縦横のサイズとか余白とかを管理する。
-
delegate
- 実際のグリッドの中に入るコンテンツを生成するウィジェットが入る。
-
SliverChildBuilderDelegate
- ビルダーのコールバックを使うsliverに子ウィジェットを提供することを責務にしたクラス。
- コンストラクタにbuilderを取る。
- sliverは全部lazy constructなので、画面に出てないwidgetは表示されるまでconstructが遅延される。この辺のややこしい処理を
SliverChildBuilderDelegate
から生成されたbuilderが行ってくれる。 - 逆に言うと、画面から見えなくなったウィジェットはdestoryされる(はずな)ので、もし画面外のに出たウィジェットを生かしたままにしたいのであれば
addAutomaticKeepAlives: true
にする。
表示したい画像のリストを用意する
適当な画像のURLを拾ってきてリストにします。
_createSampleURLs() {
final _urls = [];
const _url =
'https://kumamoto.photo/archives/_data/i/upload/2016/05/11/20160511090903-1c096f51-cu_e286.jpg';
for (var i = 0; i < 20; i++) {
_urls.add(_url);
}
return _urls;
}
final designURLs = _createSampleURLs();
出したいコンテンツの数を入れる
SliverChildBuilderDelegate.childCount
に.lengthした数を入れます。ビルドされるタイルの数を制御します。
final designURLs = _createSampleURLs();
Scaffold(
body: CustomScrollView(
slivers: <Widget>[
SliverGrid(
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 200.0,
mainAxisSpacing: 10.0,
crossAxisSpacing: 10.0,
childAspectRatio: 4.0,
),
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return // todo
},
childCount: designURLs.length,
),
),
]
)
出したいコンテンツのbuilderを定義する
最後に、出したいコンテンツのbuilderを定義します。childの数だけbuilderに指定した関数が実行されてタイルが1つ1つビルドされます。具体的には以下のような感じです。
final designURLs = _createSampleURLs();
Scaffold(
body: CustomScrollView(
slivers: <Widget>[
SliverGrid(
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 200.0,
mainAxisSpacing: 10.0,
crossAxisSpacing: 10.0,
childAspectRatio: 4.0,
),
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Container(
child: Image(
image: NetworkImage(designURLs[index]),
fit: BoxFit.fitWidth,
),
);
},
childCount: designURLs.length,
),
),
]
)
画面は以下のようになるはず。
公式のコピペでそのまま来ましたが、gridDelegate
はいじってればだいたい分かると思うので割愛します。
まとめ
SliverGrid
で動的にグリッドを実装しました。落ち着いて見ればそんなに難しくないはずなので頑張りましょう。