flutter-自定义dialog弹出层

3,777 阅读2分钟

前言

flutter开发中,由于flutter原生的人是 google,所以很多控件外观偏向与android,很多控件android开发自己的都看不过去了(相比与ios),因此需要自己定制

这里简介一下 flutter 如何定制弹窗层

系统Dialog的使用

系统Dialog的使用如下所示,使用之前需要调用showDialog,通过该方法可以直接跳出弹层(无需写入到build中),弹层内的组件在 builder参数里面传入,这里默认传入系统的 AlertDialog

showDialog(
  context: context,
  barrierColor: Colors.transparent, //设置透明底色,自定义也可能会用到
  builder: (BuildContext context) {
    return AlertDialog(
      title: const Text("测试标题"),
      content: const Text("测试内容"),
      actions: [
        TextButton(
          onPressed: () {},
          child: const Text('确认'),
        ),
        TextButton(
          onPressed: () {},
          child: const Text('取消'),
        ),
      ],
      shape:
          RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
    );
  },
);

效果如下所以,感觉有点丑

image.png

定制 Dialog

showDialog 弹出的弹层,相当于push跳转到了系统预制的一个Popup组件中,因此内部返回时需要自己pop,另外可以把它当做跳转弹层的入口即可,我们的组件只需要继承 Dialog空白组件即可

如下所示,我们自定义弹窗(纯提供方案,不求效果😂),继承自 Dialog,相当于一个新页面,我们想编辑新页面一样编辑弹窗即可

注意:我们的组件相当于嵌入到 Dialog中的一个Container中,因此如果想改变默认底色,需要在 showDialog中设置barrierColor属性即可

//这个弹层一般是通过 showDialog 弹出,实际上相当于跳转了一个新界面,因此返回需通过 Navigator pop回去
class DialogView extends Dialog {
  final String title;
  final String message;

  const DialogView({Key? key, required this.title, required this.message})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Container(
        width: 100,
        height: 140,
        color: const Color.fromRGBO(0, 0, 0, 0.7),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            Text(title, style: const TextStyle(color: Colors.white)),
            Text(message, style: const TextStyle(color: Colors.white)),
            TextButton(
              onPressed: () {
                //showDialog相当于push,因此自己返回需要pop
                Navigator.pop(context);
              },
              child: const Text('返回'),
            ),
          ],
        ),
      ),
    );
  }
}

调用方法如下所示,默认最底层的颜色,需要在这里设置 barrierColor

showDialog(
  context: context,
  barrierColor: Colors.transparent, //设置透明底色
  builder: (BuildContext context) {
    return const DialogView(
      title: "测试标题",
      message: "测试内容",
    );
  },
);

image.png

获取组件偏移量

开发弹层时,可能需要默认组件的位置信息,因此我们可以像 PopupMenuButton一样封装,接收一个组件,在弹出时,通过下面方法计算组件位置,从而更好的定制弹窗

组件渲染完成之后,可以通过组价你的context参数,间接获取组件的偏移量
RenderBox box = context.findRenderObject() as RenderBox;
final local = box.localToGlobal(Offset.zero);
print(local);

最后

这里只是记录一下一些常用的内容,有些内容也比较简单,仅供参考哈😂