Flutter 使用 SmartDialog 实现全局弹窗的完整指南

引言

在 Flutter 开发中,弹窗(Dialog) 是非常常见的交互组件,常用于提示信息、加载状态、确认操作等场景。然而,在复杂项目中,使用原生 showDialog 会带来一些问题:

  • 上下文依赖强:必须传入 BuildContext
  • 层级嵌套问题:如在 BottomSheet 中调用 Dialog 可能报错
  • 无法统一管理弹窗栈
  • 动画和样式不统一

为了解决这些问题,社区推出了许多优秀的弹窗库,其中 SmartDialog 是一个功能强大、轻量易用、支持全局调用的弹窗解决方案。

为了解决这些问题,社区推出了许多优秀的弹窗库,其中 SmartDialog 是一个功能强大、轻量易用、支持全局调用的弹窗解决方案。

1. 环境准备

1.1 添加依赖

在 pubspec.yaml 中添加 SmartDialog 的依赖:

dependencies:
  flutter:
    sdk: flutter
  smart_dialog: ^2.0.3  # 当前最新稳定版本,请根据实际情况更新

然后运行:

flutter pub get

2. 初始化 SmartDialog

为了支持全局弹窗,需要在 MaterialApp 中注册 SmartDialog 提供的导航器。

import 'package:flutter/material.dart';
import 'package:smart_dialog/smart_dialog.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      // 注册 SmartDialog
      navigatorObservers: [SmartDialogNavigatorObserver()],
      home: const HomePage(),
    );
  }
}

3. 基础使用示例

3.1 显示一个简单对话框

import 'package:smart_dialog/smart_dialog.dart';

SmartDialog.show(
  widget: AlertDialog(
    title: Text("提示"),
    content: Text("这是一个 SmartDialog 示例"),
    actions: [
      TextButton(
        onPressed: SmartDialog.dismiss,
        child: Text("确定"),
      )
    ],
  ),
);

3.2 显示加载框(Loading)

// 显示加载框
SmartDialog.showLoading();

// 模拟网络请求
await Future.delayed(Duration(seconds: 2));

// 隐藏加载框
SmartDialog.dismiss();

你也可以自定义 Loading 内容:

SmartDialog.showLoading(
  widget: CircularProgressIndicator(),
  backDismiss: false, // 是否允许点击返回关闭
);

3.3 显示 Toast 类型提示

SmartDialog 支持类似 Android Toast 的短暂提示:

SmartDialog.showToast(
  "这是一条提示信息",
  alignment: Alignment.bottomCenter,
  durationTime: 2000,
  style: TextStyle(color: Colors.white),
  background: Colors.black.withOpacity(0.6),
);

4. 高级用法

4.1 自定义弹窗内容与动画

你可以完全自定义弹窗内容,并为其添加进入/退出动画。

SmartDialog.show(
  animationType: SmartDialogAnimationType.scale, // 缩放动画
  maskColor: Colors.black54,
  clickMaskDismiss: true,
  widget: Container(
    padding: EdgeInsets.all(20),
    decoration: BoxDecoration(
      color: Colors.white,
      borderRadius: BorderRadius.circular(12),
    ),
    width: 300,
    child: Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        Text("自定义弹窗", style: TextStyle(fontSize: 18)),
        SizedBox(height: 16),
        ElevatedButton(
          onPressed: SmartDialog.dismiss,
          child: Text("关闭"),
        ),
      ],
    ),
  ),
);

支持的动画类型:

  • scale 缩放进入
  • fade 渐显渐隐
  • slide 从底部滑入
  • none 无动画

4.2 弹窗堆叠(多个弹窗同时显示)

SmartDialog 支持弹窗堆叠,即可以连续打开多个弹窗:

SmartDialog.show(widget: FirstDialog());
SmartDialog.show(widget: SecondDialog());

可以通过以下方法控制当前弹窗:

SmartDialog.dismiss(); // 关闭最上层弹窗
SmartDialog.dismissAll(); // 关闭所有弹窗

4.3 弹窗回调处理(Future 返回值)

你可以在弹窗中传递参数并获取用户选择结果:

final result = await SmartDialog.show<bool>(
  widget: AlertDialog(
    title: Text("确认操作"),
    content: Text("是否删除此条数据?"),
    actions: [
      TextButton(onPressed: () => SmartDialog.dismiss(result: false), child: Text("取消")),
      TextButton(onPressed: () => SmartDialog.dismiss(result: true), child: Text("确定")),
    ],
  ),
);

if (result == true) {
  print("用户点击了确定");
} else {
  print("用户点击了取消");
}

4.4 自定义遮罩层行为

你可以控制遮罩层是否可点击关闭、颜色、透明度等:

SmartDialog.show(
  maskColor: Colors.grey.withOpacity(0.5),
  clickMaskDismiss: false, // 禁止点击遮罩关闭
  widget: YourCustomDialogWidget(),
);

5. 最佳实践

5.1 封装通用弹窗服务类

建议封装一个 DialogService 来统一管理各类弹窗逻辑,提升复用性。

class DialogService {
  static Future<bool?> showConfirmDialog({
    required String title,
    required String content,
  }) async {
    return await SmartDialog.show<bool>(
      widget: AlertDialog(
        title: Text(title),
        content: Text(content),
        actions: [
          TextButton(
            onPressed: () => SmartDialog.dismiss(result: false),
            child: Text("取消"),
          ),
          TextButton(
            onPressed: () => SmartDialog.dismiss(result: true),
            child: Text("确定"),
          ),
        ],
      ),
    );
  }

  static void showLoading() {
    SmartDialog.showLoading(widget: CircularProgressIndicator());
  }

  static void hideLoading() {
    SmartDialog.dismiss();
  }
}

5.2 结合 GetX / Provider 使用更高效

如果你使用了 GetX 或 Provider,可以将 DialogService 作为服务注入或单例使用,进一步解耦 UI 和业务逻辑。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容