見出し画像

[Flutter]処理中と成功のモーダルを二つ続けて出す方法

チンムーです。 SIerでFlutterを使ってスマホアプリを開発しているエンジニアです。

Flutterでスマホアプリを開発する際、何かしら処理が発生している待ち時間に、「①処理中を表すモーダル」と「②処理が完了したことを表すモーダル」を二つ連続で出したいことがあると思うので、実装例を紹介します。

イメージ

①処理中モーダルには、処理中を表すぐるぐるとLoadigの文字を表示し、②完了モーダルにはSuccess!の文字とモーダルを閉じるボタンを表示するようにします。
流れとしては、画面のボタンを押す>①表示>3秒後に①が消えて②表示 

ボタンを押す
処理中
成功

①処理中モーダル

showLoadingModalという名前でメソッドを作成

void showLoadingModal(BuildContext context) {
    showDialog<void>(
      context: context,
      barrierDismissible: false,
      builder: (BuildContext context) {
        return WillPopScope(
          onWillPop: () async => false,
          child: AlertDialog(
            content: Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: const [
                CircularProgressIndicator(),
                SizedBox(width: 10),
                Text('Loading'),
              ],
            ),
          ),
        );
      },
    );
  }

②成功モーダル

処理中モーダルが消えたあとに表示するshowSuccessModal
ユーザーがCloseボタンを押すと消える



  void showSuccessModal(BuildContext context) {
    showDialog<void>(
      context: context,
      barrierDismissible: false,
      builder: (BuildContext context) {
        return AlertDialog(
          title: const Text('Success!'),
          actions: <Widget>[
            TextButton(
              child: const Text('Close'),
              onPressed: () {
                Navigator.of(context).pop();
              },
            ),
          ],
        );
      },
    );
  }

全体像

buttonと表示されたElevatedButtonを押すと、まずはshowLoadingModalを呼び出し。await Future.delayed(const Duration(seconds: 5));で5秒経過したら、Navigator.of(context).pop();でshowLoadingModalを消し、showSuccessModal(context);で自動的に成功モーダルを出します。

import 'package:flutter/material.dart';

class MyWidget extends StatelessWidget {
  const MyWidget({Key? key}) : super(key: key);

  void showLoadingModal(BuildContext context) {
    showDialog<void>(
      context: context,
      barrierDismissible: false,
      builder: (BuildContext context) {
        return WillPopScope(
          onWillPop: () async => false,
          child: AlertDialog(
            content: Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: const [
                CircularProgressIndicator(),
                SizedBox(width: 10),
                Text('Loading'),
              ],
            ),
          ),
        );
      },
    );
  }

  void showSuccessModal(BuildContext context) {
    showDialog<void>(
      context: context,
      barrierDismissible: false,
      builder: (BuildContext context) {
        return AlertDialog(
          title: const Text('Success!'),
          actions: <Widget>[
            TextButton(
              child: const Text('Close'),
              onPressed: () {
                Navigator.of(context).pop();
              },
            ),
          ],
        );
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          ElevatedButton(
              onPressed: () async {
                showLoadingModal(context);
                await Future.delayed(const Duration(seconds: 5));
                Navigator.of(context).pop(); // Close showLoadingModal
                showSuccessModal(context);
              },
              child: const Text("button"))
        ],
      ),
    );
  }
}

この記事が気に入ったらサポートをしてみませんか?