9、 Flutter Widgets 之 Dialog 对话框

4,516 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第9天,点击查看活动详情

当应用程序进行重要操作时经常需要用户进行2次确认,以避免用户的误操作,比如删除文件时,一般会弹出提示“是否要删除当前文件”,用户点击确认后才会进行删除操作,这时我们可以使用提示框(AlertDialog或者CupertinoAlertDialog)。

根据设计的不同,我们可以选择Material风格的AlertDialog或者Cupertino(ios)风格的CupertinoAlertDialog。

Material风格基础用法如下:

/**
 * @Author wywinstonwy
 * @Date 2021/12/28 8:26 上午
 * @Description:
 */
import 'package:demo202112/utils/common_appbar.dart';
import 'package:flutter/material.dart';
 
class WyDialog extends StatefulWidget {
  const WyDialog({Key? key}) : super(key: key);
 
  @override
  _WyDialogState createState() => _WyDialogState();
}
 
class _WyDialogState extends State<WyDialog> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: getAppBar("Dialog"),
      body: ListView(
        children: [
          Container(
            child: ElevatedButton(
                onPressed: () {
                  _baseDialog();
                },
                child: Text('弹框')),
          )
        ],
      ),
    );
  }
 
  _baseDialog() {
    showDialog(
        context: context,
        builder: (context) {
          return AlertDialog(
            title: Text('标题'),
            content: Text('这里可以写描述相关提示信息'),
            actions: [ TextButton(child: Text('取消'),onPressed: (){},),
              TextButton(child: Text('确认'),onPressed: (){},),],
          );
        });
  }
}

运行效果:

图片.png

Cupertino(iOS)风格效果如下:

showCupertinoDialog(
        context: context,
        builder: (context) {
          return CupertinoAlertDialog(
            title: Text('标题'),
            content: Text('这里可以写描述相关提示信息'),
            actions: [ TextButton(child: Text('取消'),onPressed: (){
              Navigator.pop(context);
            },),
              TextButton(child: Text('确认'),onPressed: (){},),],
          );
        });

iOS风格运行效果:

图片.png

showDialog和AlertDialog配合使用展示Material风格对话框,showCupertinoDialog和CupertinoAlertDialog配合使用展示iOS风格对话框,showCupertinoDialog点击空白处是无法退出对话框的,而showDialog点击空白处默认退出对话框,barrierDismissible属性控制点击空白处的行为,用法如下:

showDialog(
    barrierDismissible: false,
    )

AlertDialog的属性相对比较丰富,可以设置title样式、content样式、背景颜色、阴影值,设置是形状:

showDialog(context: context, builder: (context){
      return AlertDialog(
        title: Text('提示'),
        content: Text('确认删除吗?'),
        backgroundColor: Colors.green,
        elevation: 24,
        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(40)),
        actions: <Widget>[
          FlatButton(child: Text('取消'),onPressed: (){},),
          FlatButton(child: Text('确认'),onPressed: (){},),
        ],
      );
    });

运行效果:

图片.png

Alert参数接受

用户点击“取消”或者“确定”按钮后退出对话框,App需要知道知道用户选择了哪个选项,用法如下:

 var result = await showCupertinoDialog(
        context: context,
        barrierDismissible: true,
        builder: (context) {
          return CupertinoAlertDialog(
            title: Text('标题'),
            content: Text('这里可以写描述相关提示信息'),
            actions: [ TextButton(child: Text('取消'),onPressed: (){
              Navigator.of(context).pop('cancel');
            },),
              TextButton(child: Text('确认'),onPressed: (){
                Navigator.of(context).pop('ok');
 
              },),],
          );
        });
    print(result);

图片.png

其中await是等待异步处理结果。

SimpleDialog

如果你觉得系统提供的这2个风格的对话框不够个性,你可以试试SimpleDialog,用法和AlertDialog基本相同,如下:

var result = await showCupertinoDialog(
        context: context,
        builder: (context) {
          return SimpleDialog(
            title: Text('标题',textAlign: TextAlign.center,),
            children: [
              Container(height: 80,
              alignment: Alignment.center,
                child: Text('你确认要删除吗??》'),
              ),
              TextButton(child: Text('取消'),onPressed: (){
                Navigator.of(context).pop('cancel');
              },),
              TextButton(child: Text('确认'),onPressed: (){
                Navigator.of(context).pop('ok');
 
              },),
            ],
          );
        });
    print(result);

运行效果:

图片.png

如果你觉得这还是不够个性,那可以祭出终极大招了,直接使用Dialog,Dialog可以定制任何对话框,只需将对话框的内容给child属性:

showCupertinoDialog(
        context: context,
        builder: (context) {
          return Dialog(
            child: WyContainer(),
 
          );
        });

运行结果:

图片.png

视图悬浮加载进度指示器:

showCupertinoDialog(
        context: context,
        builder: (context) {
          return Dialog(
            child: Container(
              
              height: 300,
              width: 100,
              child: Container(
                padding: EdgeInsets.all(40),
                child: CircularProgressIndicator(),
              ),
            ),
 
          );
        });

运行效果:

图片.png

除上述的基础用法以外,实际项目中还要设计到比较好看的进度等待loading,Toast弹框等。

第三方SmartDialog

引入方式

dependencies:
  flutter_smart_dialog: any

最新版本# flutter_smart_dialog 4.5.5+6

使用

  • 主入口配置
  • 在主入口这地方需要配置下,这样就可以不传BuildContext使用Dialog了
  • 只需要在MaterialApp的builder参数处配置下即可

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomePage,
      // here
      navigatorObservers: [FlutterSmartDialog.observer],
      // here
      builder: FlutterSmartDialog.init(),
    );
  }
}

使用FlutterSmartDialog包裹下child即可,下面就可以愉快的使用SmartDialog了

SmartDialog.showLoading(msg: "test");

loading的使用

SmartDialog.showLoading();
await Future.delayed(Duration(seconds: 2));
SmartDialog.dismiss();

SmartDialog的高级用法

  • 不需要BuildContext
  • 能穿透黑暗背景,点击页面后面的对话框吗
  • 支持对话框栈,关闭指定的对话框
  • 支持定位小部件,显示指定位置对话框
  • 支持高亮功能,溶解指定的位置掩码
  • 轻松实现吐司,加载,附加对话框,自定义对话框

图片.png

总结:

本篇主要介绍了Dialog弹框的两种基础风格以及应用,自定义弹框SimpleDialog和Dialog,以及第三方SmartDialog的基本使用。望开发者可以根据业务场景更好的去应用和选择。