一、基礎概念
Flutter中的彈框分為兩種類型:Dialog和BottomSheet。Dialog一般指具有模態的彈框,使用showDialog函數實現;而BottomSheet一般指非模態的彈框,使用showModalBottomSheet實現。除此之外,還有一些其他類型的彈框,如底部菜單彈框,選擇器彈框等,這裡就不一一列舉了。
Flutter的彈框構造器通常包括以下幾個部分:彈框主體Widget、背景遮罩Widget、動畫控制器、彈框位置等等。接下來我們會重點講述這些部分的實現過程。
二、Dialog的實現
Dialog是模態的彈框類型,即彈框出現時,背景被遮擋且無法操作。
1、彈框主體Widget
在Flutter中,Dialog通常由一個AlertDialog Widget或SimpleDialog Widget構成。其中AlertDialog可以自定義其標題、內容和按鈕;而SimpleDialog只包含多個選項。
AlertDialog的構建過程類似下面的代碼:
showDialog( context: context, builder: (BuildContext context) { return AlertDialog( title: Text("彈框標題"), content: Text("彈框內容"), actions: [ FlatButton( child: Text("取消"), onPressed: () { Navigator.of(context).pop(); // 關閉彈框 }, ), FlatButton( child: Text("確定"), onPressed: () { // 實現確認邏輯 }, ), ], ); }, );
2、背景遮罩Widget
這裡我們使用了showDialog函數來構建Dialog,同時此函數還允許我們自定義彈框顯示時的遮罩背景。這可以通過指定barrierColor、barrierOpacity和barrierDismissible等屬性來實現。其中,barrierColor和barrierOpacity用於設置遮罩的顏色和透明度,而barrierDismissible則用於控制是否允許用戶點擊遮罩背景來關閉彈框(即點擊空白處關閉彈框)。
showDialog( context: context, barrierColor: Colors.black12, // 遮罩顏色 barrierOpacity: 0.5, // 遮罩透明度 barrierDismissible: false, // 是否允許點擊空白處關閉彈框 builder: (BuildContext context) { return AlertDialog( //... ); }, );
3、動畫控制器
想要Dialog具有更好的動畫效果,我們可以使用Flutter內置的動畫庫Animations。通過AnimatedWidget或AnimatedBuilder等頂層Widget,我們可以方便地構建各種動畫效果。這裡以FadeTransition為例,演示如何實現Dialog的淡入淡出效果。
class MyDialog extends StatefulWidget { const MyDialog({Key key}) : super(key: key); @override _MyDialogState createState() => _MyDialogState(); } class _MyDialogState extends State with SingleTickerProviderStateMixin { AnimationController _controller; Animation _animation; @override void initState() { super.initState(); _controller = AnimationController( duration: const Duration(milliseconds: 500), vsync: this, ); _animation = CurvedAnimation(parent: _controller, curve: Curves.easeOut); _controller.forward(); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return FadeTransition( opacity: _animation, child: Center( child: AlertDialog( title: Text("彈框標題"), content: Text("彈框內容"), actions: [ FlatButton( child: Text("取消"), onPressed: () { Navigator.of(context).pop(); }, ), FlatButton( child: Text("確定"), onPressed: () { //... }, ), ], ), ), ); } } void showMyDialog(BuildContext context) { showDialog( context: context, builder: (BuildContext context) { return MyDialog(); }, ); }
三、BottomSheet的實現
BottomSheet是非模態的彈框類型,即彈框出現時,背景不被遮擋且可以進行操作。BottomSheet有兩種類型:PersistentBottomSheet和ModalBottomSheet。其中,PersistentBottomSheet會一直保持顯示直至手動關閉,而ModalBottomSheet會在點擊某個按鈕後彈出,在外部區域進行操作時自動隱藏。
1、彈框主體Widget
在Flutter中,BottomSheet的構建器是builder屬性,它是個函數類型,返回一個Widget。另外我們也可以使用官方提供的BottomSheet Widget。與Dialog不同,BottomSheet不包含標題和按鈕等元素,通常只包含一部分滾動內容。
ModalBottomSheet( builder: (BuildContext context) { return Container( height: 200.0, child: ListView( children: [ ListTile(title: Text('選項1')), ListTile(title: Text('選項2')), ListTile(title: Text('選項3')), ListTile(title: Text('選項4')), ], ), ); }, );
2、背景遮罩Widget
與Dialog類似,BottomSheet也有相應的遮罩背景設置屬性。但由於其本身不是模態的,所以不需要只讀化背景,也就意味著無需設置barrierDismissible屬性。
showModalBottomSheet( context: context, backgroundColor: Colors.black12, // 設置背景色 builder: (BuildContext context) { return Container( height: 200.0, child: ListView( children: [ //... ], ), ); }, );
3、動畫控制器
維護動畫控制器實現BottomSheet的進入和退齣動畫。
class MyBottomSheet extends StatefulWidget { const MyBottomSheet({Key key}) : super(key: key); @override _MyBottomSheetState createState() => _MyBottomSheetState(); } class _MyBottomSheetState extends State with SingleTickerProviderStateMixin { AnimationController _controller; Animation _animation; @override void initState() { super.initState(); _controller = AnimationController( duration: const Duration(milliseconds: 500), vsync: this, ); _animation = CurvedAnimation(parent: _controller, curve: Curves.easeOut); _controller.forward(); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return SlideTransition( position: Tween( begin: Offset(0.0, 1.0), end: Offset(0.0, 0.0), ).animate(_controller), child: Container( height: 200.0, child: ListView( children: [ //... ], ), ), ); } } void showMyBottomSheet(BuildContext context) { showModalBottomSheet( context: context, builder: (BuildContext context) { return MyBottomSheet(); }, ); }
四、結語
以上就是Flutter彈框的實現方案。除了這兩種類型外,還有很多其他類型的彈框類型,每種類型都有自己的實現方式。我們需要具體問題具體分析,靈活運用。在實踐中不斷探索,準確地找到需要用到的彈框類型,並實現對應的構造器。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/185048.html