Flutterで非スクロールなWidgetに対してRefreshIndicatorを機能させる方法

はじめに

Flutterでアプリを作っていて、リソースを更新する際にRefreshIndicatorはよく使われるWidgetであると思う。しかし、これのPullToRefreshを機能させるためには、子要素がスクロール可能なものである必要がある。

しかし、そこで表示させるリストが空のときは、例えばEmptyStateのようなリストではない要素を表示をしたい場合がある。そういう場合には、SingleChildScrollViewphysics: AlwaysScrollableScrollPhysics()を適用させる回避策がよく使われるが、そうすると子要素を画面中央に表示させるのが難しくなってしまう。

今回はそういった非スクロールなWidgetを画面の中央に表示させたいが、さらにRefreshIndicatorも機能させたいときの対処法を紹介する。

方法

CustomScrollViewSliverFillRemainingを使うことで実現することができる。

RefreshIndicator(
  onRefresh: () {},
  child: const CustomScrollView(
    slivers: [
      SliverFillRemaining(
        child: Center(
          child: TargetWidget(),
        ),
      ),
    ],
  ),
);

CustomScrollViewでスクロール可能なWidgetを用意し、その中でSliverFillRemainingを使うことで画面の利用可能なスペースいっぱいにWidgetを広げることができる。これで対象のWidgetを画面の中央に配置しながら、RefreshIndicatorも機能させることができる。

おわり

CustomScrollViewは今回初めて使ったし、Sliverは知っていたがそこで使う種類がこんなにたくさんあるとは知らなかった。

FlutterはWidgetがたくさんありすぎるが、知っておかないと解決できないことが多々ある。しかし全てのWidgetを覚えようとも思わないし、覚えられるとも思えない。こういうことがあるたびに少しずつ覚えていこう。

参考

Flutter pull to refresh without ListView
Flutter pull to refresh without ListView. GitHub Gist: instantly share code, notes, and snippets.
Flutter pull to refresh without ListView favicon gist.github.com
Flutter pull to refresh without ListView