Flutter初学者如何实现主窗口右侧弹窗(类似Bottom Sheet)及打开右侧对话框
Flutter实现右侧滑出弹窗(类似Bottom Sheet)与右侧对话框
嘿,作为Flutter新手,想要实现从右侧滑出的类似Bottom Sheet的弹窗,还有右侧对话框对吧?我给你整理了两种最实用的实现方式,都是新手能快速上手的~
一、实现右侧滑出的侧边栏(类似Bottom Sheet效果)
Bottom Sheet默认是从底部弹出,我们要做右侧滑入的效果,这里有两种方案:
1. 用Scaffold自带的endDrawer(最简单)
Flutter的Scaffold组件自带了右侧抽屉endDrawer,默认就是从右侧滑入,完全满足类似Bottom Sheet的交互需求,代码量极少:
Scaffold( appBar: AppBar(title: const Text('右侧侧边栏示例')), body: Center( child: ElevatedButton( onPressed: () { // 触发打开右侧抽屉 Scaffold.of(context).openEndDrawer(); }, child: const Text('打开右侧弹窗'), ), ), endDrawer: Drawer( // 设置弹窗宽度为屏幕的70%,可以根据需求调整 width: MediaQuery.of(context).size.width * 0.7, child: Container( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text('右侧侧边栏内容', style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)), const SizedBox(height: 20), ListTile(title: const Text('选项1')), ListTile(title: const Text('选项2')), // 把内容顶到底部 const Spacer(), ElevatedButton( onPressed: () { // 关闭侧边栏 Navigator.of(context).pop(); }, child: const Text('关闭'), ) ], ), ), ), )
小提示:关闭侧边栏除了用Navigator.pop(),也可以调用Scaffold.of(context).closeEndDrawer(),效果是一样的。
2. 自定义动画侧边栏(更灵活)
如果想要更个性化的动画(比如淡入+滑入结合)、自定义遮罩层样式,那就用AnimatedContainer结合Stack来实现:
class RightSideSheetDemo extends StatefulWidget { const RightSideSheetDemo({super.key}); @override State<RightSideSheetDemo> createState() => _RightSideSheetDemoState(); } class _RightSideSheetDemoState extends State<RightSideSheetDemo> { bool _isSheetOpen = false; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('自定义右侧弹窗')), body: Stack( children: [ // 主页面内容 Center( child: ElevatedButton( onPressed: () { setState(() { _isSheetOpen = true; }); }, child: const Text('打开自定义右侧弹窗'), ), ), // 遮罩层:点击关闭弹窗 if (_isSheetOpen) GestureDetector( onTap: () { setState(() { _isSheetOpen = false; }); }, child: Container(color: Colors.black.withOpacity(0.5)), ), // 右侧弹窗本体 AnimatedContainer( duration: const Duration(milliseconds: 300), curve: Curves.easeInOut, // 控制弹窗宽度:打开时占屏幕70%,关闭时宽度为0 width: _isSheetOpen ? MediaQuery.of(context).size.width * 0.7 : 0, height: double.infinity, decoration: const BoxDecoration( color: Colors.white, borderRadius: BorderRadius.only( topLeft: Radius.circular(16), bottomLeft: Radius.circular(16), ), ), child: _isSheetOpen ? Container( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text('自定义右侧弹窗', style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)), const SizedBox(height: 20), const Expanded(child: Text('这里可以放任何你想要的内容:表单、列表、图片都没问题')), ElevatedButton( onPressed: () { setState(() { _isSheetOpen = false; }); }, child: const Text('关闭'), ) ], ), ) : const SizedBox.shrink(), ), ], ), ); } }
这种方式完全由你掌控样式和动画,适合需要高度定制的场景。
二、实现右侧对话框(Dialog)
默认的Dialog是居中显示的,要让它贴在右侧,只需要用Align组件调整位置即可:
// 封装成方法,方便调用 void showRightSideDialog(BuildContext context) { showDialog( context: context, builder: (BuildContext context) { return Align( // 把对话框定位在屏幕右侧居中位置 alignment: Alignment.centerRight, child: Container( width: MediaQuery.of(context).size.width * 0.6, height: MediaQuery.of(context).size.height * 0.8, decoration: const BoxDecoration( color: Colors.white, borderRadius: BorderRadius.only( topLeft: Radius.circular(16), bottomLeft: Radius.circular(16), ), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Padding( padding: EdgeInsets.all(16), child: Text('右侧对话框', style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)), ), const Divider(height: 0), const Expanded( child: Padding( padding: EdgeInsets.all(16), child: Text('对话框的内容区域,可以放表单、提示信息等'), ), ), Padding( padding: const EdgeInsets.all(16), child: ElevatedButton( onPressed: () { Navigator.of(context).pop(); }, child: const Text('关闭'), ), ) ], ), ), ); }, // 设置遮罩层透明度 barrierColor: Colors.black.withOpacity(0.5), ); } // 调用方式:在按钮点击时触发 // ElevatedButton( // onPressed: () => showRightSideDialog(context), // child: const Text('打开右侧对话框'), // )
这种方法本质还是用Flutter原生的showDialog,只是调整了对话框的位置,上手毫无难度。
总结一下
- 如果只是需要简单的右侧滑出弹窗,优先用
Scaffold.endDrawer,快速又省心; - 追求定制化效果,就用自定义动画的方案;
- 右侧对话框直接通过
Align调整原生Dialog的位置即可。
内容的提问来源于stack exchange,提问作者Nurlan
相关产品推荐
相关产品推荐

