📘
【Flutter】showModalBottomSheetでスワイプ可能なモーダル作成
スワイプ可能な詳細モーダルを作成
showModalBottomSheetを使ったモーダル表示をしていたのですが、子要素でスワイプでモーダルを閉じることができない様でした。
実装上子要素はスクロールできる様にしていて、スクロールはできるけどスワイプでモーダル閉じれないじゃん・・・となりますた。
結構中途半場な実装になってしまい、ぐぬぬしたので備忘録でかきこ。
解決策としてDraggableScrollableSheetを導入。
/// モーダル呼び出し
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を使うと、子要素すべてが表示(レンダリング)されます。
なので子要素がたくさんあるとアプリのパフォーマンスが下がる可能性が高まります。
モーダル表示なのでそれほど情報がないかと思いますが、気を付けることに越したことはないかと。
以上!
Discussion