時間のかかる処理の進行状況を示すプログレスインジケータ
時間のかかる処理を行う場合には、ユーザーをただじっと待たせるのではなく、処理の進捗状況を示すか、 あるいはせめて、ハングアップしていないことを示すために、何かグルグルとアニメーションで見せておくのが一般的になっています。
不思議と、このスクリーンのようなのが動いてるだけで、「あ、なんかやってるな」と安心できるんですよね。
フラッターでは、こうした種類のウィジェットを、プログレスインジケータといいます。
プログレス (progress) は日本語でいうと「進捗」とか「進行状況」のことで、インジケータ (indicator) は状況を示す「計器」的な意味になります。
リニア・インジケータとサーキュラ・インジケータ
Flutter で使えるウィジェットとしては、ProgressIndicator という名前のクラスがベースクラスとなり、 直線的に動くインジケータが LinearProgressIndicator、円形にグルグル回るタイプが CircularProgressIndicator クラスでそれぞれ実装されています。
ディターミネートとインディターミネート
プログレスインジケータの種類は、直線形か、円形かという見た目の違いのほか、Determinate と Indeterminate という種別があります。
日本語でいうと「明確な」(determinate) と「不明確な」(indeterminate) と訳せば良いでしょうか。意味としては、 determinate の方は、ハッキリと進行状況がわかる場合に使います。「現在何パーセント処理済み。あとこれくらいです」と示せるような場合です。
プログレスインジケータは value プロパティを持っていて、これに 0.0 から 1.0 までの値をセットすることによって、進捗割合を明確に表示できます。
一方、indeterminate の方は、進行状況が不明瞭の場合に使います。作業量が明確にわからず、動いていることは動いているんだけど、今どの程度か示せないような場合に使います。
インディンターミネートの場合は、単にウィジェットを表示すれば、グルグルといい塩梅に回ったりしてくれるだけです。
value をセットすることもなく、ただ置けばいいだけなので簡単ですね。
プログレスインジケータの利用サンプル
次の例では、上2つのインジケータはタイマーを使って value プロパティをセットし直しています。 下2つはインディターミネートにグルグル動かしているだけです。
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'dart:async';
void main() {
debugPaintSizeEnabled = false;
runApp(
MaterialApp(
debugShowCheckedModeBanner: false,
home: MyApp(),
),
);
}
class MyApp extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _State();
}
}
class _State extends State<MyApp> {
var _value = 0.0;
@override
void initState() {
const timeout = const Duration(milliseconds: 200);
Timer.periodic(timeout, (Timer t) {
setState(() {
_value = _value + 0.1;
if (_value > 1) {
_value = 0.0;
}
});
});
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Indicator Test'),
),
body: Container(
padding: EdgeInsets.all(30.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
// Determinate
LinearProgressIndicator(value: _value),
CircularProgressIndicator(
value: _value,
),
Divider(),
// Indeterminate
LinearProgressIndicator(),
CircularProgressIndicator()
],
),
),
);
}
}
こっそり Divider ウィジェットも使っていますが、これは単に区切り線を描いているだけのものです。