Flutter中自定义Dialog

Dialog在不同的平台,都是一种重要的交互方式,在Flutter中,Dialog也是有很多种,但大多数场景的交互,都需要根据项目的主题或一些特定的交互去实现自定义的Dialog。

为满足不同的诉求和兼容性,封装实现了两种不同的Dialog工具,可根据自己的要求,进行填充内容。

一,实现通用的自定义Dialog

根据Dialog的特性,进行抽离封装,具体内容,可自行填充或扩展

  static Future<T?> showCenterDialog<T>(BuildContext context,
      {bool barrierDismissible = true,
        required List<Widget> child,EdgeInsetsGeometry ? padding,double? radius}) async{
    return  await showDialog<T>(
      context: context,
      barrierDismissible: barrierDismissible,
      builder: (BuildContext context) {
        return WillPopScope(
          onWillPop: () {
            return Future.value(barrierDismissible);
          },
          child: Scaffold(
            backgroundColor:Colors.transparent,
            body: Center(
              child: SingleChildScrollView(
                child: Container(
                  margin: const EdgeInsets.symmetric(horizontal: 18),
                  padding: padding,
                  width: double.infinity,
                  decoration: BoxDecoration(
                      color: Colors.white,
                      borderRadius: BorderRadius.all(Radius.circular(radius??0))
                  ),
                  child: Column(
                    mainAxisSize: MainAxisSize.min,
                    mainAxisAlignment: MainAxisAlignment.center,
                    children:child,
                  ),),
              ),
            ),
            resizeToAvoidBottomInset: true,
          ),
        );
      },
    );
  }

使用时:

   showCenterDialog(context, child: [
      const Text('Hello Word')
    ]);

二,自定义bottomSheet实现高度可定制,内容可扩展的底部弹框

 showBottomSelectDialog(BuildContext context, {required Widget child}) {
    showModalBottomSheet(
        context: context,
        shape: const RoundedRectangleBorder(
            borderRadius: BorderRadius.only(
                topLeft: Radius.circular(6), topRight: Radius.circular(6))),
        isScrollControlled: true,
        enableDrag: false,
        constraints: const BoxConstraints(
            minWidth: 0,
            minHeight: 0,
            maxWidth: double.infinity,
            maxHeight: double.infinity),
        builder: (context) => child);
  }

使用时:

showBottomSelectDialog(context, child:Container(
      height: 300,
      width: double.infinity,
      child: const Column(
        children: [
          Text('Hello Flutter')
        ],
      ),
    ));

三,自定义Dialog中遇到的问题

在Flutter3.13版本之后,普通Dialog中使用TextField,键盘关闭时,TextField内容会被清空
这是可以把Dialog中的内容放到一个StatefullWidget中,即可解决。

例如:

class WarningPage extends StatefulWidget{
  final String title;
  final String message;
  const WarningPage({super.key,this.title ="Tips",this.message ="Error"});
  @override
  State<StatefulWidget> createState() {
   return _WarningState();
  }
}

class _WarningState extends State<WarningPage>{
  @override
  Widget build(BuildContext context) {
    return Material(
      type: MaterialType.transparency, //透明类型
      child: Center(
        child: Container(
          width: double.infinity,
          margin: const EdgeInsets.symmetric(horizontal: 18),
          padding: const EdgeInsets.all(10),
          decoration: BoxDecoration(
            color: Colors.white,
            borderRadius: BorderRadius.circular(4),
          ),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text(widget.title),
              Text(widget.message)
            ],
          ),
        ),
      ),
    );
  }
}

使用时:

  await showDialog(
      context: context,
      barrierDismissible: false,
      builder: (BuildContext context) {
        return WillPopScope(
          onWillPop: () {
            return Future.value(true);
          },
          child: const WarningPage(title: 'App',message: "Hello Flutter"),
        );
      },
    );

如上示例,仅提供了一种通用封装的实现,可结合实际项目自行扩展与实现。

  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值