Flutter封装一个公共的弹窗方法

817 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第22天,点击查看活动详情

通过之前的介绍,我们根据Flutter的AlertDialog组件,已经实现了如下的弹窗显示方法: image.png

但该方法的复用性并不高,我们可以发现,像弹窗的内容主体、弹窗的按钮组这些内容我们都给写死了,而不是通过调用方法传入显示的,这样会代码的复用性并不高,当需要显示另一种不同的弹窗类型时,又需要进行大量的代码修改,因此我们可以将其封装一下。原本代码如下:

Future<bool?> showLoginConfirmDialog(BuildContext context) {
  return showDialog<bool>(
    context: context,
    builder: (context) {
      return AlertDialog(
        content: Container(
          height: 300.h,
          width: 336.w,
          alignment: Alignment.center,
          child: Image.asset('assets/images/login/login_hint.png',
              width: 169.w, height: 179.h),
        ),
        actions: <Widget>[
          Container(
              alignment: Alignment.center,
              child: MaterialButton(
                  onPressed: () {
                    Get.offAllNamed("/login");
                  },
                  color: lightPrimaryColor,
                  height: 44.h,
                  minWidth: double.infinity,
                  shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(8)),
                  child: const Text(
                    '立即登录',
                    style: TextStyle(color: Colors.white),
                  )))
        ],
      );
    },
  );
}

弹窗的内容跟按钮组是通过contentactions这两个属性的Widget值来显示的,因此我们可以将其抽为showLoginConfirmDialog该方法的参数,调用该方法时传入需要自定义的弹窗内容主体Widget和按钮内容的List类型的Widget即可。

因此我们进行以下的封装,给该方法增加两个参数,类型都为Widget即可:

Future<bool?> showDeleteConfirmDialog(
    BuildContext context, Widget contentWidge, Widget actionsWidgetLsit) {
    return showDialog<bool>(
        context: context,
        builder: (context) {
        return AlertDialog(
            contentPadding: EdgeInsets.only(top: 30.h),
            content: contentWidge,
            actions: <Widget> actionsWidgetLsit,
        );
        },
    );
}        

当我们需要调用时,传入自定义的内容Widget组件跟按钮组Widget组件即可:

showDeleteConfirmDialog(
    context,
    Text('账号密码错误,请重新填写'),
    [
        Container(
            alignment: Alignment.center,
            child: GestureDetector(
                onTap: () => Navigator.of(context).pop(true),
                child: const Text('确定')))
    ]
)

更加上面代码调用后,弹窗如下:

image.png

showDeleteConfirmDialog(
    context,
    Container(
    height: 60.h,
    alignment: Alignment.center,
    decoration: BoxDecoration(
    border: Border(
        bottom:
            BorderSide(width: 1.w, color: const Color(0xFFE5E5E5))),
    ),
    child: Container(
        padding: EdgeInsets.only(bottom: 20.h),
        child: const Text("请先前往身份认证",
            style: TextStyle(color: Color(0xFF333333)))),
    [
        Flex(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            direction: Axis.horizontal,
            children: [
            Expanded(
                flex: 1,
                child: Container(
                    padding: EdgeInsets.zero,
                    child: Container(
                        alignment: Alignment.center,
                        decoration: BoxDecoration(
                        border: Border(
                            right: BorderSide(
                                width: 1.w,
                                color: const Color(0xFFE5E5E5))),
                        ),
                        child: GestureDetector(
                            onTap: () => Navigator.of(context).pop(),
                            child: const Text("取消",
                                style: TextStyle(color: secondColor))))),
            ),
            Expanded(
                flex: 1,
                child: Container(
                    padding: EdgeInsets.zero,
                    child: Container(
                        alignment: Alignment.center,
                        child: GestureDetector(
                            onTap: () => Navigator.of(context).pop(true),
                            child: Container(
                                child: const Text("前往认证",
                                    style: TextStyle(color: secondColor))))),
                )),
            ],
            )
    ]
)

上述代码实现的弹窗效果图下:

image.png

可以看见,经过封装后,如果弹窗的Ui发生改变,我们只需要在调用showDeleteConfirmDialog的时候,传入需要改变的Widget组件即可,我只对内容Widget跟按钮Widget进行了提取封装,读者可以根据自己的需求,在该基础上继续封装,把不变的都写在同一个方法内,变的作为参数传入,这也是封装的思想,从而达到提高代码复用。