Flutter自定义使用Dialog并更新Dialog中的内容

效果:
在这里插入图片描述

引言:

实现一个弹框有两种方式,一种是继承于 Dialog 来定义一个子类实现弹框效果,一种是创建一个 新的 StatelessWidget(页面)。

实际上 Flutter 提供的 Dialog 也是继承于 StatelessWidget而实现的。

1 自定义 Dialog

1.1 定义基本的弹出框

如下图所示中,定义一个基本的弹出层,除去下图中的中间的模糊部分
在这里插入图片描述

import 'package:flutter/material.dart';

/**
 * 公共弹框
 */

class CommonDialog extends Dialog {
  //子布局
  Widget childWidget;
  //左侧按钮显示文案
  String negativeText;
  //右侧按钮显示文案
  String positiveText;
  //标题显示文案
  String title;
  //显示标题下的分隔线
  bool isShowTitleDivi;
  //显示底部确认按钮上的分隔线
  bool isShowBottomDivi;
  //左侧按钮点击事件(取消)
  Function onCloseEvent;
  //右侧按钮点击事件(确认)
  Function onPositivePressEvent;

  //标题默认高度
  double defaultTitleHeight = 40.0;

  CommonDialog({
    Key key,
    @required this.childWidget,
    @required this.title = "提示",
    this.negativeText,
    this.positiveText,
    this.onPositivePressEvent,
    this.isShowTitleDivi=true,
    this.isShowBottomDivi=true,
    @required this.onCloseEvent,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return new Padding(
      padding: const EdgeInsets.all(10.0),
      child: new Material(
        type: MaterialType.transparency,
        child: new Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            //白色背景
            new Container(
              decoration: ShapeDecoration(
                color: Color(0xffffffff),
                shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.all(
                    Radius.circular(8.0),
                  ),
                ),
              ),
              margin: const EdgeInsets.all(12.0),
              child: new Column(
                children: <Widget>[
                  //标题
                  new Padding(
                    padding: const EdgeInsets.all(10.0),
                    child: Container(
                      height: defaultTitleHeight,
                      child: Center(
                        child: new Text(
                          title,
                          style: new TextStyle(
                              fontSize: 16.0, color: Color(0xff666666)),
                        ),
                      ),
                    ),
                  ),
                  //标题下的分隔线
                  new Container(
                    color: isShowTitleDivi?Color(0xffe0e0e0):Color(0xffffffff),
                    margin: EdgeInsets.only(bottom: 10.0),
                    height: 1.0,
                  ),
                  //中间显示的Widget
                  new Container(
                    constraints: BoxConstraints(minHeight: 80.0),
                    child: new Padding(
                      padding: const EdgeInsets.all(12.0),
                      child: childWidget,
                    ),
                  ),
                  //底部的分隔线
                  new Container(
                    color: isShowBottomDivi?Color(0xffe0e0e0):Colors.white,
                    margin: EdgeInsets.only(top: 10.0),
                    height: 1.0,
                  ),
                  //底部的确认取消按钮
                  this._buildBottomButtonGroup(),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildBottomButtonGroup() {
    var widgets = <Widget>[];
    if (negativeText != null && negativeText.isNotEmpty)
      widgets.add(_buildBottomCancelButton());
    if (positiveText != null && positiveText.isNotEmpty)
      widgets.add(_buildBottomPositiveButton());
    return Container(
      height: 54.0,
      child: new Row(
        mainAxisAlignment: MainAxisAlignment.end,
        children: widgets,
      ),
    );
  }

  Widget _buildBottomCancelButton() {
    return new FlatButton(
      onPressed: onCloseEvent,
      child: new Text(
        negativeText,
        style: TextStyle(
          fontSize: 16.0,
          color: Colors.grey,
        ),
      ),
    );
  }

  Widget _buildBottomPositiveButton() {
    return new FlatButton(
      onPressed: onPositivePressEvent,
      child: new Text(
        positiveText,
        style: TextStyle(
          color: Colors.red,
          fontSize: 16.0,
        ),
      ),
    );
  }
}

1.2 然后在页面中定义中间显示的Widget调用

在这里插入图片描述


  //是否满意标识位记录
  int pariseSelectIndex = 0;
  //不满意原因标识位记录
  int pariseSelectIndex2 = 0;
  //在按钮点击的时候直接调用 
  void showPariseDialog() {
    showDialog<Null>(
        context: context,
        //点击背景不消失
        barrierDismissible: false,
        builder: (context) {
          //StatefulBuilder 来构建 dialog
          //使用参数 state来更新 dialog 中的数据内容
          return StatefulBuilder(builder: (context, state) {
            //创建dialog
            return new CommonDialog(
              title: "服务完成给个好平吧!",
              negativeText: "取消",
              positiveText: "确认",
              isShowTitleDivi: false,
              onPositivePressEvent: () {
                print("确认 关闭");
                Navigator.pop(context);
              },
              onCloseEvent: () {
                print("取消 关闭");
                Navigator.pop(context);
              },
              //通过state来刷新内容
              childWidget: buildPariseChildDialog(state),
            );
          });
        });
  }

  Widget buildPariseChildDialog(state){
    return Column(
      mainAxisSize: MainAxisSize.min,
      children: <Widget>[
        Row(
          //填充
          mainAxisSize: MainAxisSize.max,
          //平分空白
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: <Widget>[
            buildPariseChildWidget(
                0, "非常满意", pariseSelectIndex == 0 ? true : false,state),
            buildPariseChildWidget(
                1, "满意", pariseSelectIndex == 1 ? true : false,state),
            buildPariseChildWidget(
                2, "不满意", pariseSelectIndex == 2 ? true : false,state),
          ],
        ),
        pariseSelectIndex==2?gridViewDefaultCount(state):Container(),
      ],
    );
  }

  //分析文章在这里 https://blog.csdn.net/zl18603543572/article/details/95037826
  Widget buildPariseChildWidget(int index, String message, bool select,state) {
    return Expanded(
      flex: 1,
      child: Container(
        margin: EdgeInsets.only(left: 5.0, right: 5.0),
        //设置 child 居中
        alignment: Alignment(0, 0),
        height: 30,
        child: new Center(
          child: new Material(
            child: new Ink(
              key: ValueKey(index),
              //设置背景
              decoration: new BoxDecoration(
                //背景
                color: Colors.white,
                //设置四周圆角 角度 这里的角度应该为 父Container height 的一半
                borderRadius: BorderRadius.all(Radius.circular(15.0)),
                //设置四周边框
                border: new Border.all(
                    width: 1, color: select ? Colors.red : Colors.grey),
              ),
              child: new InkResponse(
                borderRadius: new BorderRadius.all(new Radius.circular(15.0)),
                //点击或者toch控件高亮时显示的控件在控件上层,水波纹下层
                highlightColor: Color(0xfffbfbfb),
                //点击或者toch控件高亮的shape形状
                highlightShape: BoxShape.rectangle,
                //.InkResponse内部的radius这个需要注意的是,我们需要半径大于控件的宽,如果radius过小,显示的水波纹就是一个很小的圆,
                //水波纹的半径
                radius: 0.0,
                //水波纹的颜色 设置了highlightColor属性后 splashColor将不起效果
                splashColor: Color(0xfffbfbfb),
                //true表示要剪裁水波纹响应的界面   false不剪裁  如果控件是圆角不剪裁的话水波纹是矩形
                containedInkWell: true,

                onTap: () {
                  pariseSelectIndex = index;
                  print('click ' + pariseSelectIndex.toString());
                  state(() {});
                },
                child: new Container(
                  //不能在InkResponse的child容器内部设置装饰器颜色,否则会遮盖住水波纹颜色的,containedInkWell设置为false就能看到是否是遮盖了。
                  width: 300.0,
                  height: 50.0,
                  //设置child 居中
                  alignment: Alignment(0, 0),
                  child: Text(
                    message,
                    style: TextStyle(
                        color: select ? Colors.red : Colors.grey,
                        fontSize: 14.0),
                  ),
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }

  Widget gridViewDefaultCount(state) {
    int count = 3;
    double height = 60;

    return Container(
      margin: EdgeInsets.only(top: 20),
      //设置 child 居中
      alignment: Alignment(0, 0),
      height: height,
      //边框设置
      decoration: new BoxDecoration(
        //背景
        color: Color(0xfff6f6f6),
        //设置四周圆角 角度
        borderRadius: BorderRadius.all(Radius.circular(4.0)),
        //设置四周边框
        border: new Border.all(width: 1, color: Color(0xfff6f6f6)),
      ),
      child: initListWidget(count,state),
    );
  }

  Widget initListWidget(int count,state) {
    List<Widget> lists = [];
    List<Widget> clists = [];

    lists.add(buildPariseSelectChildWidget(
        0, "出车慢", pariseSelectIndex2 == 0 ? true : false,state));
    lists.add(buildPariseSelectChildWidget(
        1, "服务差", pariseSelectIndex2 == 1 ? true : false,state));
    lists.add(buildPariseSelectChildWidget(
        2, "态度不好", pariseSelectIndex2 == 2 ? true : false,state));
    clists.add(Row(
      mainAxisSize: MainAxisSize.max,
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: lists,
    ));

    return Column(
      crossAxisAlignment: CrossAxisAlignment.center,
      mainAxisAlignment: MainAxisAlignment.center,
      children: clists,
    );
  }

  Widget buildPariseSelectChildWidget(int index, String message, bool select,state) {
    return InkWell(
      //单击事件响应
      onTap: () {

        pariseSelectIndex2 = index;
        state(() {});
      },
      child: Row(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          Image.asset(
            select
                ? ImageUtil.getImgsPath("phone_select_icon")
                : ImageUtil.getImgsPath("phone_noselect_icon"),
            width: 20.0,
            height: 20.0,
          ),
          Padding(
            child: Text(
              message,
              style: TextStyle(fontSize: 13, color: Color(0xff666666)),
            ),
            padding: EdgeInsets.only(left: 5.0),
          )
        ],
      ),
    );
  }
早起的年轻人 CSDN认证博客专家 移动开发 项目管理 Java
只要用心去做,每一件事情还是有可能成功的,当然成功是没有界限的,只不过是达到自己心里的那个目标,公众号:我的大前端生涯,一个爱喝茶的程序员,通常会搞搞SpringBoot 、Herbinate、Mybatiys、Android、iOS、Flutter、Vue、小程序等.
©️2020 CSDN 皮肤主题: 代码科技 设计师:Amelia_0503 返回首页