Flutter プログレスインジケーターの種類と全画面表示

Flutter

何か時間がかかる処理をする時にプログレスインジケーターを表示しておきたい場合があります。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:
    背景色を黒の半透明にしている

閉じる時は、Navigatorpop すれば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();
              },
            ),
          ],
        ),
      ),
    );
  }
}

コメント

タイトルとURLをコピーしました