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),),
                );
              },
            ),
          ),
        ],
      )
    );
  }
}

SliverAppBar SliverFixedExtentList

  • 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,
            ),
          ),
        ],
      )
    );
  }
}

SliverAppBar SliverGrid

基本は同じですが、グリッドの場合は「SliverGrid」を使います。
「SliverGrid」では、gridDelegateによって、グリッドの調整を行います。
gridDelegateには以下2つの方法で、グリッドを制御できます。

  • SliverGridDelegateWithMaxCrossAxisExtentCrossAxis方向に表示する数を画面のサイズから判定します。
  • SliverGridDelegateWithFixedCrossAxisCountCrossAxis方向に表示する数を固定で指定します。

GridViewの内容と似かよっているので、詳細については、こちらを参照してください。
MainAxisやCrossAxisについては、こちらが参考になるかと思います。