質問: ページ遷移するまで時間がかかる場合にスピナー(CircularProgressIndicator()) を表示させたいです。 スピナー表示に関しては上記ページで動画再生準備完了までの間スピナーを表示するサンプルがあるのですが、FutureBuilderを使っており、futureに関してはVideoPlayerControllerクラスを使えば、その中で自動的に用意してくれるので、それをFutureBuilderの引数に設定すれば、それだけでできる、ということらしいです。 ということで、そういうのを用意してくれていれば、それを使えばいいと思うのですが。 つまり、今回の場合、ページ遷移した時にコンプリートするfutureを用いてFutureBuilderを作る必要があるのだと思うのですが。 このfutureは自分で実装するしかないのでしょうか? 「ページ遷移するまでスピナー表示させたい」という要求自体かなり一般的な気がするので、すでにそういうfutureを作る仕組みが用意されているのならそれを使いたいのですが、あるんでしょうか?
回答: (1)も(2)も実現可能です。 (1)に関しては「ページ遷移で完了」ではなく、「ファイル作成で完了」という考え方にシフトしたほうがやりやすいと思います。ボタン押下時、ファイルダウンロード完了時に`setState`でスピナー表示/非表示を切り替えるなど。 イメージ↓ 動画選択時の処理 ``` bool _loading = false; void _downloadVideo() async { // スピナー表示 setState(() => _loading = true); _file = await xxxxxxxxxxxx().then((data) { // ダウンロード終了後 // スピナー非表示 setState(() => _loading = false); // 画面遷移 Navigator.xxxxxxxxxxxxxxxxxxxxxxxxxx; }); } ... child: _loading ? CircularProgressIndicator() // _loadingがtrueならスピナー表示 : VideoListView(), // falseなら一覧表示 ... ``` スピナーをオーバーレイ表示にしたい場合はこっちが向いている? (2)は、`FutureBuilder`で`ssnapshot.hasData`が`false`の時はスピナー表示、`true`になったらスピナーを消すという風にやればいいと思います。 イメージ↓ ``` ... child: FutureBuilder( future: _downloadVideo, builder: (BuildContext context, AsyncSnapshot snapshot) { if (snapshot.hasData) { // ダウンロード完了したら動画再生画面を表示 return VideoPlayerView(); } else if (snapshot.hasError) { // エラー表示 return Error(); } else { // ダウンロード完了するまではスピナー表示 return CircularProgressIndicator(); } }, ), ... Future _downloadVideo() async { // ファイルダウンロード _file = await xxxxxxxxxxxxxxxxxx(); // ファイル準備 return await xxxxxxxxxxxxxx(_file ); } ```