何か時間がかかる処理をする時にプログレスインジケーターを表示しておきたい場合があります。Flutter で使用できるプログレスインジケーターの種類と、全画面でプログレスインジケーターを表示するダイアログについて解説します。
プログレスインジケーターの種類
サーキュラー(円形)/ リニア(線形)
Flutter のプログレスインジケーターには、サーキュラー(円形)タイプとリニア(線形)タイプがあります。
// サーキュラー(円形)タイプ
CircularProgressIndicator(),
// リニア(線形)タイプ
LinearProgressIndicator(),
こんな感じのアニメーションです:

※リニアタイプのインジケーターはアプリ上部のバーの下に付いている使用例が多いかと思います。
ちなみに、iOS タイプの CupertinoActivityIndicator というのもあります。
進捗が分かる場合
プログレスインジケーターには「進捗が分かる場合」と「進捗が不定の場合」の2つの状態があります。
デフォルトは「進捗が不定」なので延々とアニメーションするだけですが、進捗が分かる場合は、value プロパティに 0.0〜1.0 の値を入れてあげると進捗割合で表示する事ができます。
var _value = 0.0; // 進捗の値を変更してsetStateなどで更新する
LinearProgressIndicator(value: _value),
アニメーションはこうなります:

全画面でプログレスインジケーターを表示する
よくある使われ方で、何かの処理中に画面全体が暗くなって真ん中でインジケーターがクルクル回っているのをよく見かけると思いますが、Flutter でこの表示にする方法を解説します。
この表示は showGeneralDialog を使えばいい感じに出来ます。
// 全画面プログレスダイアログ
showGeneralDialog(
context: context,
barrierDismissible: false,
transitionDuration: Duration(milliseconds: 300),
barrierColor: Colors.black.withOpacity(0.5),
pageBuilder: (BuildContext context, Animation animation, Animation secondaryAnimation) {
return Center(
child: CircularProgressIndicator(),
);
}
);
各プロパティの設定は以下の通り。
- barrierDismissible:
画面タップで閉じるのを無効にしている - transitionDuration:
表示時のフェードインアウト時間を300msに設定している - barrierColor:
背景色を黒の半透明にしている
閉じる時は、Navigator で pop すればOKです。
// 全画面表示を閉じる
Navigator.of(context).pop();
サンプルコード
全画面プログレスダイアログのサンプルコードです。

「表示」ボタンを押すと全画面プログレスダイアログが表示され、3秒後に閉じます。
import 'package:flutter/material.dart';
import 'dart:async'; // Future.delayed
void main() => runApp(MyApp());
// MyApp ウイジェットクラス
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.light(),
home: MyHomePage(title: 'ProgressIndicator Demo'),
);
}
}
// MyHomePage ウイジェットクラス
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
// MyHomePage ステートクラス
class _MyHomePageState extends State<MyHomePage> {
// 全画面プログレスダイアログを表示する関数
void showProgressDialog() {
showGeneralDialog(
context: context,
barrierDismissible: false,
transitionDuration: Duration(milliseconds: 300),
barrierColor: Colors.black.withOpacity(0.5),
pageBuilder: (BuildContext context, Animation animation, Animation secondaryAnimation) {
return Center(
child: CircularProgressIndicator(),
);
}
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('全画面プログレスダイアログ'),
SizedBox(height: 150),
RaisedButton(
child: Text('表示'),
onPressed: () async {
// 全画面プログレスダイアログを表示
showProgressDialog();
// 3秒後にダイアログを閉じる
await Future.delayed(Duration(seconds: 3));
Navigator.of(context).pop();
},
),
],
),
),
);
}
}
コメント