時間のかかる処理の進行状況を示すプログレスインジケータ

時間のかかる処理を行う場合には、ユーザーをただじっと待たせるのではなく、処理の進捗状況を示すか、 あるいはせめて、ハングアップしていないことを示すために、何かグルグルとアニメーションで見せておくのが一般的になっています。

不思議と、このスクリーンのようなのが動いてるだけで、「あ、なんかやってるな」と安心できるんですよね。

フラッターでは、こうした種類のウィジェットを、プログレスインジケータといいます。

プログレス (progress) は日本語でいうと「進捗」とか「進行状況」のことで、インジケータ (indicator) は状況を示す「計器」的な意味になります。

リニア・インジケータとサーキュラ・インジケータ

Flutter で使えるウィジェットとしては、ProgressIndicator という名前のクラスがベースクラスとなり、 直線的に動くインジケータが LinearProgressIndicator、円形にグルグル回るタイプが CircularProgressIndicator クラスでそれぞれ実装されています。

ディターミネートとインディターミネート

プログレスインジケータの種類は、直線形か、円形かという見た目の違いのほか、DeterminateIndeterminate という種別があります。

日本語でいうと「明確な」(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 ウィジェットも使っていますが、これは単に区切り線を描いているだけのものです。

ここまでお読みいただき、誠にありがとうございます。SNS 等でこの記事をシェアしていただけますと、大変励みになります。どうぞよろしくお願いします。

© 2024 Flutter 入門