Flutter-Dialog组件详解

·  阅读 2052

在实际开发中,我们会经常用到各种Dialog,这里我介绍8种常见的 Dialog 和如何自定义 Dialog。

图片.gif

下面介绍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);
}
复制代码

Simulator Screen Shot - iPhone 12 Pro Max - 2021-12-02 at 07.53.15.png

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);
}
复制代码

Simulator Screen Shot - iPhone 12 Pro Max - 2021-12-02 at 07.54.01.png

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);
}
复制代码

Simulator Screen Shot - iPhone 12 Pro Max - 2021-12-02 at 07.54.13.png

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);
}
复制代码

Simulator Screen Shot - iPhone 12 Pro Max - 2021-12-02 at 07.54.19.png

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}');
}
复制代码

Simulator Screen Shot - iPhone 12 Pro Max - 2021-12-02 at 07.54.27.png

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);
}
复制代码

Simulator Screen Shot - iPhone 12 Pro Max - 2021-12-02 at 07.54.34.png

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))),
                    ],
                  ),
                )
              ],
            ),
          )
        ],
      ),
    );
  }
}
复制代码

Simulator Screen Shot - iPhone 12 Pro Max - 2021-12-02 at 07.54.40.png

Simulator Screen Shot - iPhone 12 Pro Max - 2021-12-02 at 07.54.46.png

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,
  );
}
复制代码

Simulator Screen Shot - iPhone 12 Pro Max - 2021-12-02 at 07.55.23.png

以上就是写的常用的Dialog。其实在实际开发中可以参考系统的组件,我们可以根据自己的需求来自定义,控制传入的title、message、文字颜色、字体、大小、事件的回调等等。

分类:
iOS
标签:
分类:
iOS
标签:
收藏成功!
已添加到「」, 点击更改