Flutter 8种Dialog详解
在实际开发中,我们会经常用到各种Dialog
,这里我介绍8种常见的 Dialog 和如何自定义 Dialog。
下面介绍8种样式的Dialog
1.AlertDialog
AlertDialog
是比较常用的 Dialog,这是系统提供的控件。我们可以根据传参控制显示的样式,这里我都写了一个异步获取结果的方法.
AlertDialog的属性:
title:标题
titlePadding:标题内边距
titleTextStyle:标题样式
content:内容,推荐用SingleChildScrollView包裹
contentPadding:EdgeInsets.fromLTRB(24.0, 20.0, 24.0, 24.0),内容内边距
contentTextStyle:内容样式
actions:按钮集合,可以放多个
actionsPadding:EdgeInsets.zero,actions内边距
buttonPadding:按钮内边距
backgroundColor:背景色
elevation:阴影
shape:形状
scrollable = false:
具体实现代码示例:
_alertDialog() async { var result = await showDialog( context: context, builder: (context) { return AlertDialog( title: Text('这是一个Dialog'), content: Text('这是一个alertDialog类型的Dialog'), actions: <Widget>[ TextButton( child: Text( '取消', style: TextStyle(color: Colors.grey), ), onPressed: () { Navigator.pop(context, "取消"); }), TextButton( child: Text( '确定', style: TextStyle(color: Colors.blue), ), onPressed: () { Navigator.pop(context, "确定"); }, ), ], ); }); print(result); }复制代码
2. SimpleDialog
SimpleDialog
这个是在屏幕中间显示,可选项的一个弹窗,这在实际中也经常用到
SimpleDialog属性:
title:标题
titlePadding:EdgeInsets.fromLTRB(24.0, 24.0, 24.0, 0.0),标题内边距
titleTextStyle:标题样式
children:子节点
contentPadding:EdgeInsets.fromLTRB(0.0, 12.0, 0.0, 16.0),内容内边距
backgroundColor:背景色
elevation:阴影
shape:形状
SimpleDialog的实现代码示例:
_simpleDialog() async { var result = await showDialog( context: context, builder: (context) { return SimpleDialog( title: Text('选择对应内容'), children: <Widget>[ SimpleDialogOption( child: Text('这是第一个选项'), onPressed: () { Navigator.pop(context, 'A'); }, ), Divider(), SimpleDialogOption( child: Text('这是第二个选项'), onPressed: () { Navigator.pop(context, 'B'); }, ), Divider(), SimpleDialogOption( child: Text('这是第三个选项'), onPressed: () { Navigator.pop(context, 'C'); }, ), ], ); }); print(result); }复制代码
3. ShowModalBottomSheet
ModalBottomSheet
底部面板,相当于弹出了一个新页面,有点类似于 ActionSheet
ModalBottomSheet的属性:
context:BuildContext
builder:WidgetBuilder
backgroundColor:背景色
elevation:阴影
shape:形状
barrierColor:遮盖背景颜色
isDismissible:点击遮盖背景是否可消失
enableDrag:下滑消失
ModalBottomSheet 的实现代码示例:
_modelBottomSheet() async { var result = await showModalBottomSheet( context: context, builder: (context) { return Container( height: 234, child: Column( children: <Widget>[ ListTile( title: Text( '相机', textAlign: TextAlign.center, ), onTap: () { Navigator.pop(context, '相机'); }, ), Divider(), ListTile( title: Text( '图片', textAlign: TextAlign.center, ), onTap: () { Navigator.pop(context, '图片'); }, ), Container( height: 10, color: Color(0xFFf2f2f2), ), ListTile( title: Text('取消', textAlign: TextAlign.center), onTap: () { Navigator.pop(context, '取消'); }, ), ], ), ); }, ); print(result); }复制代码
4. CupertinoAlertDialog
这个是苹果样式的 AlertDialog,第一个是 Android 样式的
CupertinoAlertDialog的属性:
title:标题
content:内容
actions = const []:actions
scrollController:控制器
actionScrollController:action控制器
insetAnimationDuration = const Duration(milliseconds: 100):动画时长
insetAnimationCurve = Curves.decelerate:动画显示的曲线
注意点:
需要使用 showCupertinoDialog,当然用 showDialog 也是可以的,区别就是 showCupertinoDialog 点击弹框外是不能取消弹框的,showDialog是可以的,然后就是背景透明度也是不一样的
如果加入了国际化的话或报错'The getter alertDialogLabel was called on null',需要配置FallbackCupertinoLocalisationsDelegate
CupertinoAlertDialog 内部嵌套的是 SingleChildScrollView,内容超长是不会有问题的,不需要重复嵌套
Material 跟 Cupertino 组件也是可以混用的
CupertinoAlertDialog的实现代码示例:
void showCupertinoDialogStyle() async { var result = await showCupertinoDialog( context: context, builder: (context) { return CupertinoAlertDialog( title: Text('这是标题'), content: Text( "这样的样式就和苹果原生一样", ), actions: <Widget>[ CupertinoButton( child: Text("取消"), onPressed: () { Navigator.pop(context); }, ), CupertinoButton( child: Text("确定"), onPressed: () { Navigator.pop(context); }, ), ], ); }); print(result); }复制代码
5. CupertinoActionSheet
苹果式样的底部弹出选择框。
CupertinoActionSheet 的属性:
actions的子组件一般使用CupertinoActionSheetAction
组件,CupertinoActionSheetAction 组件向按钮组件一样,提供了子控件和onPressed回调,isDefaultAction属性设置为true时,文字加粗,isDestructiveAction属性设置为true时,文字颜色变为红色
CupertinoActionSheet的实现代码示例:
void showCupertinoActionSheet() async { var result = await showCupertinoModalPopup( context: context, builder: (context) { return CupertinoActionSheet( title: Text('温馨提示'), message: Text('是否要删除?'), actions: [ CupertinoActionSheetAction( child: Text('删除'), onPressed: () {}, isDefaultAction: true, ), CupertinoActionSheetAction( child: Text('暂时不删'), onPressed: () {}, isDestructiveAction: true, ), ], cancelButton: CupertinoActionSheetAction( child: Text('取消'), onPressed: () { Navigator.of(context).pop('cancel'); }, ), ); }); print('${result}'); }复制代码
6. 确认弹窗
AlertDialog的实现代码示例:
void showCupertinoDialogSure() { var dialog = CupertinoAlertDialog( title: Text('标题标题'), content: Text( "这是一个描述文本", style: TextStyle(fontSize: 20), ), actions: <Widget>[ CupertinoButton( child: Text("确定"), onPressed: () { Navigator.pop(context); }, ), ], ); showDialog(context: context, builder: (_) => dialog); }复制代码
7. 自定义弹窗
这样包含两个,升级弹窗和Alert弹窗。
实现代码示例:
import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; //定义枚举类型 enum DialogType { upgrade, alert } class CustomDialog extends Dialog { final String? title; //标题 final String? content; //内容 final DialogType? dialogType; final void Function()? cancelCallBack; final void Function()? confirmCallBack; CustomDialog( {this.title, this.content, this.dialogType, this.confirmCallBack, this.cancelCallBack}); @override Widget build(BuildContext context) { switch (this.dialogType) { case DialogType.upgrade: return Material( type: MaterialType.transparency, child: Center( child: upgradeDialog(context), ), ); break; case DialogType.alert: return Material( type: MaterialType.transparency, child: Center( child: customAlertDialog(context), ), ); break; default: return Material( type: MaterialType.transparency, child: Center( child: upgradeDialog(context), ), ); } } //自定义Alert弹窗 Widget customAlertDialog(BuildContext context) { return Container( height: 300, margin: EdgeInsets.only(left: 40, right: 40), color: Colors.white, child: Column( children: [ Padding( padding: EdgeInsets.all(20), child: Stack( children: [ Align( child: Text( title!, style: TextStyle(fontSize: 20, color: Color(0xFF2D2D2D)), ), ), Align( alignment: Alignment.centerRight, child: InkWell( child: Icon(Icons.close), onTap: () { Navigator.of(context).pop(); }, ), ), ], ), ), Divider(), Container( width: double.infinity, margin: EdgeInsets.all(10), child: Text( content!, textAlign: TextAlign.left, ), ) ], ), ); } //自定义升级弹窗 Widget upgradeDialog(BuildContext context) { return Container( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( margin: EdgeInsets.only(left: 20, right: 20), decoration: const ShapeDecoration( color: Color(0xfff2f2f2), shape: RoundedRectangleBorder( borderRadius: BorderRadius.all( Radius.circular(10), ), ), ), child: Column( children: [ Container( height: 250, decoration: const BoxDecoration( borderRadius: BorderRadius.only( topLeft: Radius.circular(10), topRight: Radius.circular(10)), image: DecorationImage( image: AssetImage('images/head_icon.png'), fit: BoxFit.cover, )), ), SizedBox( height: 20, ), Container( padding: EdgeInsets.only(left: 10, right: 10), width: double.infinity, child: const Text( '本次更新', style: TextStyle( fontSize: 20, color: Color(0xFF2D2D2D), decoration: TextDecoration.none), textAlign: TextAlign.left, ), ), SizedBox( height: 15, ), Container( padding: EdgeInsets.only(left: 10, right: 10), width: double.infinity, child: Text( '解决了一些已知问题', style: TextStyle( fontSize: 16, color: Color(0xFF333333), decoration: TextDecoration.none), textAlign: TextAlign.left, ), ), SizedBox( height: 20, ), Divider(), Container( height: 40, margin: EdgeInsets.only(bottom: 15), child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ TextButton( onPressed: () { Navigator.of(context).pop(); this.confirmCallBack!(); }, child: Text( '升级', style: TextStyle(fontSize: 18), ), ), VerticalDivider( color: Colors.grey, width: 1, ), TextButton( onPressed: () { Navigator.of(context).pop(); this.cancelCallBack!(); }, child: Text('暂不升级', style: TextStyle(fontSize: 18))), ], ), ) ], ), ) ], ), ); } }复制代码
8. Toast提示框
这里我用到了一个包fluttertoast
,需要先在./pubspec.yaml中引入包
fluttertoast: ^8.0.8复制代码
然后在终端运行
flutter pub get复制代码
接着就在项目中导入
import 'package:fluttertoast/fluttertoast.dart';复制代码
fluttertoast 属性参数:
msg:toast展示的信息 gravity:toast展示的位置 timeInSecForIosWeb:显示的秒数,到时间自动消失 backgroundColor:背景色 textColor:文字颜色 fontSize:字体大小复制代码
实现的示例代码
showToast() { Fluttertoast.showToast( msg: '取消点击', toastLength: Toast.LENGTH_SHORT, gravity: ToastGravity.BOTTOM, timeInSecForIosWeb: 1, backgroundColor: Colors.black45, textColor: Colors.white, fontSize: 16.0, ); }复制代码
以上就是写的常用的Dialog。其实在实际开发中可以参考系统的组件,我们可以根据自己的需求来自定义,控制传入的title、message、文字颜色、字体、大小、事件的回调等等。
作者:周糖果
链接:https://juejin.cn/post/7036915754607837192