Flutter入门(34):Flutter 组件之 Dialog 弹框(Dialog,Alert)详解

1. 基本介绍

SimpleDialog、AlertDialog、CupertinoAlertDialog、Dialog 都是最常见的弹框提示。
CupertinoAlertDialog 是 iOS 风格弹框。
showDialog、showCupertinoDialog 是两个调用弹框的 api,基本没啥区别,使用也没有什么限制。

Dialog.gif

2. 示例代码

代码下载地址。如果对你有帮助的话记得给个关注,代码会根据我的 Flutter 专题不断更新。

3. 属性介绍

3.1 SimpleDialog 属性介绍

SimpleDialog属性 介绍
title 标题
titlePadding 标题外间距,默认为 const EdgeInsets.fromLTRB(24.0, 24.0, 24.0, 0.0),
titleTextStyle 标题样式 TextStyle
children 子控件,可以随意自定义
contentPadding 内容外间距,默认为 const EdgeInsets.fromLTRB(0.0, 12.0, 0.0, 16.0)
backgroundColor 背景色
elevation 阴影高度
semanticLabel 语义标签
shape 形状 ShapeBorder

3.2 AlertDialog 属性介绍

AlertDialog属性 介绍
title 标题
titlePadding 标题外间距,默认为 const EdgeInsets.fromLTRB(24.0, 24.0, 24.0, 0.0),
titleTextStyle 标题样式 TextStyle
content 内容控件
contentPadding 内容外间距,默认为 const EdgeInsets.fromLTRB(24.0, 20.0, 24.0, 24.0)
contentTextStyle 内容文本样式 TextStyle
actions 事件子控件组
actionsPadding 事件子控件间距,默认为 EdgeInsets.zero,
actionsOverflowDirection 事件过多时,竖向展示顺序,只有正向和反向,默认为 VerticalDirection.down
actionsOverflowButtonSpacing 事件过多时,竖向展示时,子控件间距
buttonPadding actions 中每个按钮边缘填充距离,默认为左右各 8.0
backgroundColor 背景色
elevation 阴影高度
semanticLabel 语义标签
insetPadding 对话框距离屏幕边缘间距,默认为 EdgeInsets.symmetric(horizontal: 40.0, vertical: 24.0)
clipBehavior 超出部分剪切方式,Clip.none
shape 形状 ShapeBorder
scrollable 是否可以滚动,默认为 false

3.3 CupertinoAlertDialog 属性介绍

CupertinoAlertDialog属性 介绍
title 标题
content 内容控件
actions 事件子控件组
scrollController 滚动控制器,内容超出高度,content 可以滑动
actionScrollController actions 滚动控制器,actions超出高度,actions 可以滑动
insetAnimationDuration 动画时间,默认为 const Duration(milliseconds: 100)
insetAnimationCurve 动画效果,渐进渐出等等,默认为 Curves.decelerate

3.4 Dialog 属性介绍

Dialog属性 介绍
backgroundColor 背景色
elevation 阴影高度
insetAnimationDuration 动画时间,默认为 const Duration(milliseconds: 100)
insetAnimationCurve 动画效果,渐进渐出等等,默认为 Curves.decelerate
insetPadding 对话框距离屏幕边缘间距,默认为 EdgeInsets.symmetric(horizontal: 40.0, vertical: 24.0)
clipBehavior 超出部分剪切方式,Clip.none
shape 形状 ShapeBorder
child 自定义弹框

4. Dialog调用方法详解

4.1 showDialog 详解

showDialog 是控制 Dialog 弹出的 api。下文有具体使用,这里就简单介绍一下常用属性。

showDialog常用属性 介绍
context 上下文
builder (context){ return widget;} 返回一个 Widget 作为弹框展示内容
barrierDismissible 点击背后蒙层是否关闭弹框,默认为 true
barrierColor 背后蒙层颜色
useSafeArea 是否使用安全区域,默认为 true
useRootNavigator 是否使用根导航,默认为 true
routeSettings 路由设置
child 子控件,和使用 builder 返回一个 widget 同样效果

4.2 showCupertinoDialog 详解

showCupertinoDialog 也是控制 Dialog 弹出的 api。其实与 showDialog 一样,两者都可以调用各种弹框,但是 showCupertinoDialog 默认是不可以点击空白区域隐藏的。

showCupertinoDialog常用属性 介绍
context 上下文
builder (context){ return widget;} 返回一个 Widget 作为弹框展示内容
useRootNavigator 是否使用根导航,默认为 true
barrierDismissible 点击背后蒙层是否关闭弹框,默认为 false
routeSettings 路由设置

5. SimpleDialog 详解

SimpleDialog 的属性都比较简单,下方写两个不同的 Dialog,备注基本写的很明白了,就不赘述了,不明白的属性可以参考最上方表格。

import 'package:flutter/material.dart';

class FMDialogVC extends StatefulWidget {
  @override
  FMDialogState createState() => FMDialogState();
}

class FMDialogState extends State  {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(title: Text("Dialog"),),
      body: ListView(
        padding: EdgeInsets.all(15),
        children: [
          _showDialog(context, "SimpleDialog - Normal", _simpleDialogForNormal(context)),

        ],
      ),
    );
  }

  RaisedButton _showDialog(context, title, dialog){
    return RaisedButton(
      child: Text("$title"),
      // 设置异步回调
      onPressed: () async {
        // 接收点击自己反参的值
        var result = await showDialog(
          context: context,
          barrierColor: Colors.red.withAlpha(30),
          barrierDismissible: true,
          // builder: (context){
          //   return dialog;
          // },
          child: dialog,
        );
        print(result);
      },
    );
  }

  SimpleDialog _simpleDialogForNormal(context){
    return SimpleDialog(
      title: Text("SimpleDialog - Normal"), // 标题
      titlePadding: EdgeInsets.fromLTRB(20, 20, 0, 0), // 标题外间距
      // 标题样式 TextStyle
      titleTextStyle: TextStyle(
        color: Colors.blue,
        fontSize: 25,
      ),
      contentPadding: EdgeInsets.only(left: 15, right: 15), // 内容外间距
      backgroundColor: Colors.white, // 背景色
      // 子控件,可以随意自定义
      children: [
        Container(
          child: Text("这就是最简单的 Dialog 了, 也可以在这里自定义样式。"),
          alignment: Alignment.center,
          padding: EdgeInsets.all(40),
        ),
        FlatButton(
          onPressed: (){
            // 隐藏弹框
            Navigator.pop(context, 'SimpleDialog - Normal, 我知道了');
          },
          child: Text("我知道了"),
          textColor: Colors.white,
          color: Colors.blue,
        ),
      ],
    );
  }
}
SimpleDialog - Normal.png
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(title: Text("Dialog"),),
      body: ListView(
        padding: EdgeInsets.all(15),
        children: [
          _showDialog(context, "SimpleDialog - Normal", _simpleDialogForNormal(context)),
          _showDialog(context, "SimpleDialog - Shape", _simpleDialogForShape(context)),
        ],
      ),
    );
  }

  SimpleDialog _simpleDialogForShape(context){
    return SimpleDialog(
      title: Text("SimpleDialog - Shape"), // 标题
      titlePadding: EdgeInsets.fromLTRB(20, 20, 0, 0), // 标题外间距
      // 标题样式 TextStyle
      titleTextStyle: TextStyle(
        color: Colors.blue,
        fontSize: 25,
      ),
      contentPadding: EdgeInsets.only(left: 15, right: 15), // 内容外间距
      backgroundColor: Colors.yellow, // 背景色
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(30),
        side: BorderSide(
          color: Colors.red,
          width: 1,
        ),
        
      ),
      // 子控件,可以随意自定义
      children: [
        Container(
          child: Text("这就是最简单的 Dialog 了, 也可以在这里自定义样式。"),
          alignment: Alignment.center,
          padding: EdgeInsets.all(40),
        ),
        FlatButton(
          onPressed: (){
            // 隐藏弹框
            Navigator.pop(context, 'SimpleDialog - Shape, 我知道了');
          },
          child: Text("我知道了"),
          textColor: Colors.white,
          color: Colors.blue,
        ),
      ],
    );
  }
SimpleDialog - Shape.png

6. AlertDialog 详解

AlertDialog 的属性都比较简单,下方写两个不同的 Dialog,备注基本写的很明白了,就不赘述了,不明白的属性可以参考最上方表格。

  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(title: Text("Dialog"),),
      body: ListView(
        padding: EdgeInsets.all(15),
        children: [
          _showDialog(context, "SimpleDialog - Normal", _simpleDialogForNormal(context)),
          _showDialog(context, "SimpleDialog - Shape", _simpleDialogForShape(context)),
          _showDialog(context, "AlertDialog - Normal", _alertDialogForNormal(context)),
          // _showDialog(context, "AlertDialog - Shape", _alertDialogForShape(context)),
        ],
      ),
    );
  }

  AlertDialog _alertDialogForNormal(context){
    return AlertDialog(
      title: Text("AlertDialog - Normal"), // 标题
      titlePadding: EdgeInsets.fromLTRB(20, 20, 0, 0), // 标题外间距
      // 标题样式 TextStyle
      titleTextStyle: TextStyle(
        color: Colors.blue,
        fontSize: 25,
      ),
      contentPadding: EdgeInsets.only(left: 15, right: 15), // 内容外间距
      // 内容样式 TextStyle
      contentTextStyle: TextStyle(
        color: Colors.grey,
        fontSize: 16,
      ),
      // 内容控件
      content: Container(
        height: 100,
        child: Column(
          children: [
            Padding(padding: EdgeInsets.all(15),),
            Text("这是最简单的 AlertDialog,也可以自定义样式"),
          ],
        ),
      ),

      backgroundColor: Colors.white, // 背景色

      actionsPadding: EdgeInsets.all(15), // 事件子控件间距
      // 事件子控件
      actions: [
        Text("也可以不放按钮的"),
        FlatButton(
          onPressed: (){
            Navigator.pop(context, 'AlertDialog - Normal, cancel');
          },
          child: Text("cancel")
        ),
        FlatButton(
          onPressed: (){
            Navigator.pop(context, 'AlertDialog - Normal, ok');
          },
          child: Text("ok"),
        ),
      ],
    );
  }
AlertDialog - Normal.png
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(title: Text("Dialog"),),
      body: ListView(
        padding: EdgeInsets.all(15),
        children: [
          _showDialog(context, "SimpleDialog - Normal", _simpleDialogForNormal(context)),
          _showDialog(context, "SimpleDialog - Shape", _simpleDialogForShape(context)),
          _showDialog(context, "AlertDialog - Normal", _alertDialogForNormal(context)),
          _showDialog(context, "AlertDialog - Shape", _alertDialogForShape(context)),
        ],
      ),
    );
  }

  AlertDialog _alertDialogForShape(context){
    return AlertDialog(
      title: Text("AlertDialog - Shape"), // 标题
      titlePadding: EdgeInsets.fromLTRB(20, 20, 0, 0), // 标题外间距
      // 标题样式 TextStyle
      titleTextStyle: TextStyle(
        color: Colors.blue,
        fontSize: 25,
      ),
      contentPadding: EdgeInsets.only(left: 15, right: 15), // 内容外间距
      // 内容样式 TextStyle
      contentTextStyle: TextStyle(
        color: Colors.grey,
        fontSize: 16,
      ),
      // 内容控件
      content: Container(
        height: 100,
        child: Column(
          children: [
            Padding(padding: EdgeInsets.all(15),),
            Text("这是最简单的 AlertDialog,也可以自定义样式"),
          ],
        ),
      ),

      backgroundColor: Colors.white, // 背景色

      actionsPadding: EdgeInsets.all(15), // 事件子控件间距
      // 事件子控件
      actions: [
        Text("也可以不放按钮的"),
        FlatButton(
            onPressed: (){
              Navigator.pop(context, 'AlertDialog - Shape, cancel');
            },
            child: Text("cancel")
        ),
        FlatButton(
          onPressed: (){
            Navigator.pop(context, 'AlertDialog - Shape, ok');
          },
          child: Text("ok"),
        ),
      ],
      // shape 形状
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(30),
        side: BorderSide(
          color: Colors.red,
          width: 1,
        ),

      ),
    );
  }
AlertDialog - Shape.png

7. CupertinoAlertDialog 详解

CupertinoAlertDialog 是一个 iOS 风格的弹出框,与其他弹框使用方式大同小异,就不细讲了。

7.1 使用 showCupertinoDialog 调用 api 展示 CupertinoAlertDialog 普通样式。

  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(title: Text("Dialog"),),
      body: ListView(
        padding: EdgeInsets.all(15),
        children: [
          _showDialog(context, "SimpleDialog - Normal", _simpleDialogForNormal(context)),
          _showDialog(context, "SimpleDialog - Shape", _simpleDialogForShape(context)),
          _showDialog(context, "AlertDialog - Normal", _alertDialogForNormal(context)),
          _showDialog(context, "AlertDialog - Shape", _alertDialogForShape(context)),
          _showCupertinoDialog(context, "CupertinoAlertDialog - Normal", _cupertinoAlertDialog(context)),
        ],
      ),
    );
  }

  // showCupertinoDialog 展示 Dialog,showCupertinoDialog 相比 showDialog 缺少部分属性,并且默认点击背景不隐藏
  RaisedButton _showCupertinoDialog(context, title, dialog){
    return RaisedButton(
      child: Text("$title"),
      onPressed: () async {
        var result = await showCupertinoDialog(
          context: context,
          builder: (context){
            return dialog;
          },
        );
      },
    );
  }

  CupertinoAlertDialog _cupertinoAlertDialog(context){
    return CupertinoAlertDialog(
      title: Text("CupertinoAlertDialog - Normal"),
      content: Container(
        height: 100,
        child: Column(
          children: [
            Padding(padding: EdgeInsets.all(15),),
            Text("这是最简单的 CupertinoAlertDialog,也可以自定义样式"),
          ],
        ),
      ),
      actions: [
        FlatButton(
            onPressed: (){
              Navigator.pop(context, 'CupertinoAlertDialog - Normal, cancel');
            },
            child: Text("cancel")
        ),
        FlatButton(
          onPressed: (){
            Navigator.pop(context, 'CupertinoAlertDialog - Normal, ok');
          },
          child: Text("ok"),
        ),
      ],
    );
  }
CupertinoAlertDialog - Normal.png

7.2 使用 showCupertinoDialog 调用 api 展示 CupertinoAlertDialog 多个按钮样式。

  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(title: Text("Dialog"),),
      body: ListView(
        padding: EdgeInsets.all(15),
        children: [
          _showDialog(context, "SimpleDialog - Normal", _simpleDialogForNormal(context)),
          _showDialog(context, "SimpleDialog - Shape", _simpleDialogForShape(context)),
          _showDialog(context, "AlertDialog - Normal", _alertDialogForNormal(context)),
          _showDialog(context, "AlertDialog - Shape", _alertDialogForShape(context)),
          _showCupertinoDialog(context, "CupertinoAlertDialog - Normal", _cupertinoAlertDialog(context)),
          _showCupertinoDialog(context, "CupertinoAlertDialog - Three", _cupertinoAlertDialogForThree(context)),
        ],
      ),
    );
  }

  CupertinoAlertDialog _cupertinoAlertDialogForThree(context){
    return CupertinoAlertDialog(
      title: Text("CupertinoAlertDialog - Normal"),
      content: Container(
        height: 100,
        child: Column(
          children: [
            Padding(padding: EdgeInsets.all(15),),
            Text("这是最简单的 CupertinoAlertDialog,也可以自定义样式"),
          ],
        ),
      ),
      actions: [
        FlatButton(
            onPressed: (){
              Navigator.pop(context, 'CupertinoAlertDialog - Three, cancel');
            },
            child: Text("cancel")
        ),
        FlatButton(
            onPressed: (){
              Navigator.pop(context, 'CupertinoAlertDialog - Three, delete');
            },
            child: Text(
              "delete",
              style: TextStyle(
                color: Colors.red,
              ),
            ),
        ),
        FlatButton(
          onPressed: (){
            Navigator.pop(context, 'CupertinoAlertDialog - Three, ok');
          },
          child: Text("ok"),
        ),
      ],
    );
  }
CupertinoAlertDialog - Three.png

7.3 使用 showDialog 调用 api 展示 CupertinoAlertDialog 多个按钮样式。

  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(title: Text("Dialog"),),
      body: ListView(
        padding: EdgeInsets.all(15),
        children: [
          _showDialog(context, "SimpleDialog - Normal", _simpleDialogForNormal(context)),
          _showDialog(context, "SimpleDialog - Shape", _simpleDialogForShape(context)),
          _showDialog(context, "AlertDialog - Normal", _alertDialogForNormal(context)),
          _showDialog(context, "AlertDialog - Shape", _alertDialogForShape(context)),
          _showCupertinoDialog(context, "CupertinoAlertDialog - Normal", _cupertinoAlertDialog(context)),
          _showCupertinoDialog(context, "CupertinoAlertDialog - Three", _cupertinoAlertDialogForThree(context)),
          _showDialog(context, "Use showDialog 展示 CupertinoAlertDialog - Normal", _cupertinoAlertDialog(context)),
        ],
      ),
    );
  }
showDialog - CupertinoAlertDialog.png

8. Dialog 详解

Dialog 是自由度最高的弹框,样式完全根据自己给 child 的值来展示,下边我就简单写一个自定义弹框。

  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(title: Text("Dialog"),),
      body: ListView(
        padding: EdgeInsets.all(15),
        children: [
          _showDialog(context, "SimpleDialog - Normal", _simpleDialogForNormal(context)),
          _showDialog(context, "SimpleDialog - Shape", _simpleDialogForShape(context)),
          _showDialog(context, "AlertDialog - Normal", _alertDialogForNormal(context)),
          _showDialog(context, "AlertDialog - Shape", _alertDialogForShape(context)),
          _showCupertinoDialog(context, "CupertinoAlertDialog - Normal", _cupertinoAlertDialog(context)),
          _showCupertinoDialog(context, "CupertinoAlertDialog - Three", _cupertinoAlertDialogForThree(context)),
          _showDialog(context, "Use showDialog 展示 CupertinoAlertDialog - Normal", _cupertinoAlertDialog(context)),
          _showDialog(context, "Dialog - Custom", _customDialog(context)),
        ],
      ),
    );
  }

  Dialog _customDialog(context){
    return Dialog(
      backgroundColor: Colors.yellow.shade100, // 背景色
      elevation: 4.0, // 阴影高度
      insetAnimationDuration: Duration(milliseconds: 300), // 动画时间
      insetAnimationCurve: Curves.decelerate, // 动画效果
      insetPadding: EdgeInsets.all(30), // 弹框距离屏幕边缘距离
      clipBehavior: Clip.none, // 剪切方式
      child: Container(
        width: 300,
        height: 300,
        color: Colors.white,
        alignment: Alignment.center,
        child: Column(
          children: [
            Text("Custom Dialog", style: TextStyle(color: Colors.blue, fontSize: 25),),
            Padding(padding: EdgeInsets.all(15)),
            Text("这是一个最简单的自定义 Custom Dialog"),
            Padding(padding: EdgeInsets.all(15),),
            FlatButton(
              onPressed: (){
                // 隐藏弹框
                Navigator.pop(context, 'SimpleDialog - Normal, 我知道了');
              },
              child: Text("我知道了"),
              textColor: Colors.white,
              color: Colors.blue,
            ),
          ],
        ),
      ),
    );
  }
Dialog custom.png

9. 技术小结

Dialog 是使用非常广泛的弹框,这里需要多加练习,其实更多的样式以及布局考验的仅仅是其他组件组合的基本功。

你可能感兴趣的:(Flutter入门(34):Flutter 组件之 Dialog 弹框(Dialog,Alert)详解)