📘

【Flutter】showModalBottomSheetでスワイプ可能なモーダル作成

に公開

スワイプ可能な詳細モーダルを作成

showModalBottomSheetを使ったモーダル表示をしていたのですが、子要素でスワイプでモーダルを閉じることができない様でした。

実装上子要素はスクロールできる様にしていて、スクロールはできるけどスワイプでモーダル閉じれないじゃん・・・となりますた。

結構中途半場な実装になってしまい、ぐぬぬしたので備忘録でかきこ。

解決策としてDraggableScrollableSheetを導入。

https://api.flutter.dev/flutter/widgets/DraggableScrollableSheet-class.html
https://api.flutter.dev/flutter/material/showModalBottomSheet.html

/// モーダル呼び出し
  showModalBottomSheet(
            context: context,
            isScrollControlled: true,
            useRootNavigator: true,
            builder: (BuildContext context) {
              return DraggableScrollableSheet( /// ここに差込。
                initialChildSize: 0.95, // 初期表示時の高さ
                maxChildSize: 0.95, // 最大の高さ
                builder: (context, scrollController) {
                  return SingleChildScrollView( /// スクロール
                    controller: scrollController,
                    child: HogeDetailModal(
                      scrollController: scrollController,
                    ),
                  );
                },
              );
            },
          );

///////////// 別ファイル

class HogeDetailModal extends StatelessWidget {
  /// Constructor
  const HogeDetailModal({
    required this.scrollController,
    super.key,
  });

  /// スクロールコントローラー
  final ScrollController scrollController;

  
  Widget build(BuildContext context) {
    final maxHeight = MediaQuery.of(context).size.height * 0.95;

    return Container(
      width: double.infinity,
      height: maxHeight,
      decoration: BoxDecoration(
        borderRadius: const BorderRadius.only(
          topLeft: Radius.circular(10),
          topRight: Radius.circular(10),
        ),
      ),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
     // ヘッダー
          hogehogeHeaderArea(context)
          const Gap(16),
     // モーダルの中身
          Flexible(
            child: SingleChildScrollView(
              controller: scrollController,
              child: Column(
                children: [
                  gigiArea(context),
                  gagaArea(context),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}

showModalBottomSheet以下にSingleChildScrollViewがありますが、DraggableScrollableSheet と同期させるため。

HogeDetailModalにもSingleChildScrollViewがありますが、こちらも上記同じ理由。
プロパティでスクロールコントローラー渡しています。

ユーザー的にはモーダル出てきたらススクロールも出来てワイプで閉じれたら楽なのかなと。

SingleChildScrollViewの利用の注意点

なんでもかんでもSingleChildScrollViewを使うのはあまりよろしくなくて、SingleChildScrollViewを使うと、子要素すべてが表示(レンダリング)されます。

なので子要素がたくさんあるとアプリのパフォーマンスが下がる可能性が高まります。

モーダル表示なのでそれほど情報がないかと思いますが、気を付けることに越したことはないかと。

https://zenn.dev/rionishino/articles/c4041f0073c151

以上!

Discussion