Flutter写一个简单的Dialog,可以自定义布局,可以设置是否可以取消,点击对话框外Dialog消失

因为需求原因,需要一个类似安卓中的Dialog,可以自行决定一些行为,比如是否可以取消,点弹窗之外是否可以取消,自定义位置,自定义内容布局等等,废话不多说直接看代码:

class CustomDialog extends BaseDialog {
  final String title;
  final String msg;
  final Color cancelColor;
  final Color confirmColor;
  final String cancel;
  final String confirm;
  final VoidCallback onCancel;
  final VoidCallback onConfirm;
  final Widget contentView;
  final AlignmentGeometry alignment;
  final num maxWidth;
  final num maxHeight;
  final num mWidth;
  final num mHeight;
  final bool touchOutCancel;
  final bool cancelable;

  final Decoration decoration;

  CustomDialog({
    this.title,
    this.msg,
    this.cancel,
    this.confirm,
    this.contentView,
    this.cancelColor,
    this.confirmColor,
    this.onCancel,
    this.onConfirm,
    this.alignment,
    this.maxWidth,
    this.maxHeight,
    this.mWidth,
    this.mHeight,
    this.decoration,
    this.touchOutCancel = true,
    this.cancelable,
  });

  @override
  Widget build(BuildContext context) {
    List<Widget> children = [];
    if (title?.isNotEmpty == true)
      children.add(Padding(
        padding: EdgeInsets.only(top: height(8)),
        child: Text(
          title,
          style: TextStyle(
              color: textColor, fontSize: sp(17), fontWeight: FontWeight.w600),
        ),
      ));
    if (msg?.isNotEmpty == true) {
      children.add(Padding(
        padding:
            EdgeInsets.symmetric(vertical: height(16), horizontal: width(16)),
        child: Text(
          msg,
          style: TextStyle(fontSize: sp(16), fontWeight: FontWeight.w500),
        ),
      ));
    }

    if (contentView != null) {
      children.add(contentView);
    }
    List<Widget> rowChildren = [];
    if (onCancel != null && StringUtils.isNotEmpty(cancel)) {
      rowChildren.add(Expanded(
          child: InkWell(
        onTap: onCancel,
        child: Container(
          child: Center(
            child: Text(
              cancel,
              style: TextStyle(
                  color: cancelColor ?? Colors.black54,
                  fontSize: sp(16),
                  fontWeight: FontWeight.w400),
            ),
          ),
        ),
      )));
    }
    if (onConfirm != null && StringUtils.isNotEmpty(confirm)) {
      rowChildren.add(Expanded(
          child: InkWell(
        onTap: onConfirm,
        child: Container(
          child: Center(
            child: Text(
              confirm,
              style: TextStyle(
                  color: confirmColor ?? accentColor,
                  fontSize: sp(16),
                  fontWeight: FontWeight.w400),
            ),
          ),
        ),
      )));
    } else {}

    if (rowChildren.isNotEmpty) {
      children.add(Container(
        height: 1,
        decoration: BoxDecoration(color: Colors.grey[100]),
      ));
      if (rowChildren.length == 2) {
        rowChildren.insert(
            1,
            Container(
              width: 1,
              height: 30,
              decoration: BoxDecoration(color: Colors.grey[100]),
            ));
      }
      children.add(Flexible(
        child: Container(
          height: height(40),
          child: Row(
            mainAxisSize: MainAxisSize.max,
            children: rowChildren,
          ),
        ),
      ));
    }
    Offset offset;

    return WillPopScope(
        child: Listener(
          onPointerDown: touchOutCancel == true
              ? (event) {
                  Offset pos = event.position;
                  if (offset == null ||
                      pos.dy != offset.dy ||
                      pos.dx != offset.dx) {
                    Navigator.pop(context);
                  }
                }
              : null,
          child: Material(
            type: MaterialType.transparency,
            child: Align(
              alignment: alignment,
              child: GestureDetector(
                onPanDown: (event) {
                  offset = event.globalPosition;
                },
                child: Container(
                  constraints: BoxConstraints(
                      maxHeight: maxHeight ?? ScreenUtil.screenHeightDp * .8,
                      maxWidth: maxWidth ?? ScreenUtil.screenWidthDp * .8),
                  width: mWidth ?? ScreenUtil.screenWidthDp * 0.8,
                  height: mHeight,
                  decoration: decoration ??
                      BoxDecoration(
                          color: white, borderRadius: BorderRadius.circular(6)),
                  child: Column(
                    mainAxisSize: MainAxisSize.min,
                    mainAxisAlignment: MainAxisAlignment.start,
                    crossAxisAlignment: CrossAxisAlignment.center,
                    children: children,
                  ),
                ),
              ),
            ),
          ),
        ),
        onWillPop: () {
          return Future.value(cancelable ?? true);
        });
  }
}

代码看起来也很简单

这里的BaseDialog很简单,也贴下:

class BaseDialog extends Dialog {
  num width(w) {
    return ScreenUtil.getInstance().setWidth(w);
  }

  num height(h) {
    return ScreenUtil.getInstance().setHeight(h);
  }

  num sp(h) {
    return ScreenUtil.getInstance().setSp(h);
  }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mr大伟哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值