LoginSignup
1
1

【Flutter】処理が成功した時だけシートを自動で閉じる

Last updated at Posted at 2023-07-31

はじめに

Flutterにはマテリアルデザインのボトムシートを簡単に実装するshowModalBottomSheetというメソッドが用意してあります。
ボトムシートとは画面下端から上端にスライドして表示されるシートで、showModalBottomSheetを使用すると図のようなよくあるUIを簡単に表示することができます。

showModalBottomSheetの詳しい使い方については前回の記事をご覧ください。

目標

モーダルボトムシートを開いた状態で、何らかの処理を行い、成功の場合だけシートを自動で閉じる。

実装

前回記事より、showModalBottomSheetの基本的な実装は次の通りです。

showModalBottomSheetの使い方
  child: GestureDetector(
    onTap: () async {
      await showModalBottomSheet<void>(
        context: context,
        backgroundColor: Colors.transparent,
        isScrollControlled: true,
        enableDrag: true,
        barrierColor: Colors.black.withOpacity(0.5),
        builder: (context) {
          return _BottomSheet(); //シートUI
          });
        },
    child: Container(
      padding: EdgeInsets.all(5),
      decoration: BoxDecoration(
        color: Colors.blue, borderRadius: BorderRadius.circular(4)),
      child: Text(
        'showModalBottomSheet',
        style: TextStyle(color: Colors.white),
      ),
    ),
  ),

ここでは何らかのメニューリストのイメージで、まずボトムシート状にリスト状にウィジェットを配置し、
このリストをタップすることで、ある処理が実行され成功した時のみシートが自動で閉じる、という動きを実装していきたいと思います。

リストメニューの配置

ここではリストメニューをContainerウィジェットで作成していきます。
それぞれGestureDetectorでラップすることで、タップされた時の処理を実装できるようにします。

実行する処理の実装

例として以下のようなリストをタップされた時の処理を実装します。
リストのGestureDetectoronTapコールバックに任意の処理を指定します。
mathパッケージをインポートし、nextBoolでランダムなブール値を生成します。TRUEなら処理成功、FALSEなら失敗とし、try-catchで囲み、エラーハンドリングを行えるようにしておきます。

シートを閉じる動きの実装

ここまでの流れで、ボトムシート自体の実装およびシートを開くshowModalBottomSheetの実装が完了しました。
しかしボトムシートを閉じる処理がありません。
実はボトムシートのクラスであるModalBottomSheetクラスは、Flutterにおける通常の画面遷移処理においても継承し利用されているModalRouteクラスを継承しており、Navigatorによる画面遷移が可能となっております。

したがってpopを実行すれば、シートを閉じることができます。
以下の処理を追加し、処理成功時シートが自動で閉じるようにします。

Navigator.of(context).pop();

成功時だけシートを閉じる

今回擬似的に処理の成功・不成功を発生させるため、ランダムにブール値を発生させ、TRUEなら成功、FALSEなら失敗、という処理を実装しました。
処理が失敗した時にはエラーメッセージを表示し、処理が成功した時にはシートが自動で閉じる(popされる)ようにします。

以上の実装結果がこちらです。

class _BottomSheet extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      height: double.infinity,
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.only(
          topLeft: Radius.circular(10),
          topRight: Radius.circular(10),
        ),
      ),
      margin: EdgeInsets.only(top: 80),
      child: ListView.builder(
        physics: const BouncingScrollPhysics(),
        itemCount: 3, //適当なメニュー数
        itemBuilder: (context, index) {
          return GestureDetector(
            behavior: HitTestBehavior.opaque,
            onTap: () {
              try {
                //メニューを押した時に実行したい処理
                //ここではランダムなBool値を生成し、TRUE:成功、FALSE:失敗とする
                if (math.Random().nextBool()) {
                  //成功したら画面を閉じる
                  Navigator.of(context).pop();
                } else {
                  throw Error();
                }
              } catch (_) {
                //処理失敗時
                await showDialog(
                  context: context,
                  builder: (context) {
                    return const SimpleDialog(
                      titlePadding: EdgeInsets.all(20),
                      title: Text('エラーが発生しました'),
                    );
                  },
                );
              }
            },
            child: Container(
              decoration: BoxDecoration(
                color: Colors.white,
                border: Border(
                  bottom: BorderSide(color: Colors.grey),
                ),
              ),
              width: double.infinity,
              padding: EdgeInsets.only(top: 20, bottom: 20),
              child: Center(
                child: Text(index.toString()), //適当なメニュー名
              ),
            ),
          );
        },
      ),
    );
  }
}
  

おわりに

今回の記事ではリストメニューが表示されたモーダルボトムシートを想定して、各メニューの処理実行が成功した時だけシートを閉じる実装方法をご紹介しました。
この動作は、処理が成功した時は自動でメニューを閉じ、実行結果がエラーの場合のみユーザにリトライ動作を促すことを意図して設計しております。
次回は成功・失敗よりもさらに詳細な処理結果に応じた画面遷移の方法をご紹介したいと思います。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1