【Flutter】Sliverを基本から

2023/06/30に公開

はじめに

この記事では Sliver について、Flutter初心者向けに説明しています。そのため詳細よりも全体感を掴むことに重きをおいています。何となく使ったことがある、という状態を抜け出す一助になれば幸いです。

Sliverとは

Sliverとは、スクロール可能な領域です。
「破片にする、分割する」という意味の通り、スクロールできる領域の断片となります。

スクロールを実現するためのウィジェットは、内部的にSliverを使用しています。

SingleChildScrollView

スクロールを実装するにあたって、最もシンプルなウィジェットの1つとして SingleChildScrollView があります。 これは、そのChild要素を1つのSliverとしてスクロール可能にするウィジェットです。

ListView

スクロールのパフォーマンスを考慮するなら、ListViewウィジェットが役立ちます。これは子要素を複数のSliverに分割してスクロール可能にするウィジェットです。画面内のSliverのみが実際にレンダリングされるため、小要素がたくさんある場合はパフォーマンスに優れています。 GridViewなども同様です。

スクロール領域をまとめる

複雑なスクロールUIを実現するために、複数のSliverをまとめる必要があったりします。例えば、画面上にListViewGridViewを半分ずつ表示する場合、一度のスクロール操作で動かせるのは、ListViewGridViewのどちらか1つだけです。

ListViewGridViewを組み合わせる例は極端ですが、スクロールに応じてアニメーションするAppBarなども同じです。一度のスクロール操作で異なるSliverの操作を行うことで、複雑なスクロールUIを実現することができます。

https://api.flutter.dev/flutter/material/SliverAppBar-class.html

実装の例

CustomScrollView

Sliverを扱うWidgetはたくさんありますが、その中からまずは CustomScrollView を見てみます。

https://api.flutter.dev/flutter/widgets/CustomScrollView-class.html

以下は、公式ドキュメントのサンプルコードです。

CustomScrollView(
  slivers: <Widget>[
    const SliverAppBar(
      ...,
    ),
    SliverGrid(
      gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
        maxCrossAxisExtent: 200.0,
        mainAxisSpacing: 10.0,
        ...,
      ),
      delegate: SliverChildBuilderDelegate(
        (BuildContext context, int index) {
          return Container(...);
        },
        childCount: 20,
      ),
    ),
    SliverFixedExtentList(
      itemExtent: 50.0,
      delegate: SliverChildBuilderDelegate(
        (BuildContext context, int index) {
          return Container(...);
        },
      ),
    ),
  ],
)

ポイント

  • children ではなく slivers (Sliver = スクロール片 を子要素とする)
    • Sliver以外を与えることはできません
  • sliversの中には、delegate を要求するものがあります
    • そのsliverが特別に要求する情報や関数です
    • どんなdelegateが必要かは使用するsliverによって異なります
    • WidgetのContsraintsやリストのサイズを指定するなどが多い印象です

Sliverが要求されている場合、当然ながらSliver以外のWidgetを与えることはできません。例えばCustomScrollViewの中でPaddingを設定したい場合は SliverPaddingWidgetを使用します。
このように Sliver〇〇 の形になっているWidgetがあるので、使いたいWidgetにSliverのprifixをつけて探してみると、イメージするレイアウトが組みやすいかと思います。

まとめ

  • 普段意識していなくても、実は内部的にSliverを使用している
  • 複数のSliverをまとめて制御する場合、Sliverを自分で扱うためのWidgetが利用できる
  • Sliver系のWidgetはパラメータとしてdelegateを要求することがある
  • よく使用するWidgetのSliverバージョンが存在する

Discussion