SliverAppBar
SliverAppBar
「SliverAppBar」はスクロールに応じてヘッダー要素を隠すことができるようになるウィジェットです。
「SliverAppBar」の一覧要素には、大きく分けてリストとグリッドの2種類あるのでそれぞれ説明していきます。
最初に「SliverFixedExtentList」についての解説をしていきます。
SliverFixedExtentList
class _MainPageState extends State<MainPage> {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('SliverAppBar'),
),
body: CustomScrollView(
slivers: <Widget>[
const SliverAppBar(
floating: true,
pinned: true,
snap: true,
expandedHeight: 250.0,
flexibleSpace: FlexibleSpaceBar(
title: Text('Demo'),
),
),
SliverFixedExtentList(
itemExtent: 200.0,
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Container(
alignment: Alignment.center,
color: Colors.lightBlue[100 * (index % 9)],
child: Text('list item $index', style: TextStyle(fontSize: 30),),
);
},
),
),
],
)
);
}
}
floating
がtrueの時は、リストの最初に戻らなくても上にスクロールするとヘッダーが表示されるようになります。pinned
がtrueの時は、ヘッダーを完全に隠すのではなく、タイトルの1行分を残した状態で表示されるようになります。snap
がtrueの時は、ヘッダーがスクロールにより中途半端に表示されなくなり、一気に最大表示されます。
※snap
をtrueにしたい時は必ずfloating
がtrueである必要があります。expandedHeight
は表示するヘッダーの高さになります。
「SliverAppBar」はこのように「CustomScrollView」の子要素として作成します。
「CustomScrollView」のスクロール動作に対して、「SliverAppBar」のヘッダー要素が隠れるようになります。
body: CustomScrollView(
slivers: <Widget>[
const SliverAppBar(
),
]
),
次に表示するリストを作成します。itemExtent
が行の高さになり、リストの内容はdelegate
にて行になる要素を作成してください。
今回は「SliverChildBuilderDelegate」を使うことで、表示している範囲のみ要素を生成するようにします。delegate
にはスクロール時に現在の行番号(index
)を受け取ることができます。
SliverFixedExtentList(
itemExtent: 200.0,
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Container(
alignment: Alignment.center,
color: Colors.lightBlue[100 * (index % 9)],
child: Text('list item $index', style: TextStyle(fontSize: 30),),
);
},
),
),
「SliverChildBuilderDelegate」はchildCount
を指定することで、表示件数を制限することも可能です。childCount
を指定しない場合は、スクロールに応じて無限にコンテンツを構築しようとするので、動的に内容を制御している場合は、表示したいコンテンツが足りなくなる可能性があるので注意してください。
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Container(
alignment: Alignment.center,
color: Colors.lightBlue[100 * (index % 9)],
child: Text('list item $index', style: TextStyle(fontSize: 30),),
);
},
childCount: 10,
),
これにより、ヘッダーがスクロールで表示、非表示される「SliverAppBar」が完成です。
SliverGrid
次に「SliverGrid」による、グリッド一覧の作り方もみてみましょう。
class _MainPageState extends State<MainPage> {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('SliverAppBar'),
),
body: CustomScrollView(
slivers: <Widget>[
const SliverAppBar(
floating: true,
pinned: true,
snap: true,
expandedHeight: 250.0,
flexibleSpace: FlexibleSpaceBar(
title: Text('Demo'),
),
),
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: 100,
),
),
],
)
);
}
}
基本は同じですが、グリッドの場合は「SliverGrid」を使います。
「SliverGrid」では、gridDelegate
によって、グリッドの調整を行います。gridDelegate
には以下2つの方法で、グリッドを制御できます。
SliverGridDelegateWithMaxCrossAxisExtent
はCrossAxis
方向に表示する数を画面のサイズから判定します。SliverGridDelegateWithFixedCrossAxisCount
はCrossAxis
方向に表示する数を固定で指定します。
GridViewの内容と似かよっているので、詳細については、こちらを参照してください。
MainAxisやCrossAxisについては、こちらが参考になるかと思います。