今回はサンプルとして買い物追加画面をボトムシートで表示する実装を行います。
1. ボトムシートを開く
// shopping_page.dart
await showModalBottomSheet<AddItemResult>(
context: context,
isScrollControlled: true, // 高さを自由に設定できる
builder: (_) => const AddItemSheet(),
);
isScrollControlled: true を付けると、シートの高さを画面いっぱいまで広げられます。
2. ドラッグで高さ変更できる UI
// add_item_sheet.dart
class AddItemSheet extends StatefulWidget {
const AddItemSheet({super.key});
@override
State<AddItemSheet> createState() => _AddItemSheetState();
}
class _AddItemSheetState extends State<AddItemSheet> {
@override
Widget build(BuildContext context) {
return DraggableScrollableSheet(
expand: false,
initialChildSize: 0.7, // 初期表示 70%
minChildSize: 0.5, // 最小 50%
maxChildSize: 0.9, // 最大 90%
builder: (context, scrollController) {
return SafeArea(
child: SingleChildScrollView(
controller: scrollController,
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// ドラッグハンドル
Center(
child: Container(
width: 40,
height: 4,
margin: const EdgeInsets.only(bottom: 16),
decoration: BoxDecoration(
color: Colors.grey[400],
borderRadius: BorderRadius.circular(2),
),
),
),
Text('買い物を追加'),
// ... 入力フォーム
],
),
),
),
);
},
);
}
}
3. 閉じ方
// キャンセル
OutlinedButton(
onPressed: () => Navigator.pop(context),
child: const Text('戻る'),
)
// 追加完了後
Navigator.pop(
context,
AddItemResult(name: controller.text, category: selectedCategory),
);
まとめ
showModalBottomSheet + DraggableScrollableSheet の組み合わせで、追加フォームを画面遷移なし(ボトムシート)で表示できました。