Flutter中Get.snackbar和Get.dialog关闭冲突问题记录

背景:

在使用GetX框架时,同时使用了Get.snackbar提示框和Get.dialog加载框,当这两个widget同时存在时,Get.dialog加载框调用Get.back()无法正常关闭。

冲突解释:

之所以会产生冲突,是因为Get.snackbar在关闭时会有一个动画,这个动画的默认持续时间为1s,这个动画的持续时间内,Get.snackbar并没有真正意义上的关闭,这时候我们调用Get.back()是无法关闭Get.dialog。

实现:

  1. 创建一个统一的SnackBarManager去管理提示框。

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

    class SnackBarManager {
    factory SnackBarManager() => instance;

    static final SnackBarManager instance = SnackBarManager._internal();

    SnackBarManager._internal();

    String _lastMessage = '';

    int _lastDuration = 0;

    int _lastTime = 0;

    void showSnackBar(String title, String message, {Color? backgroundColor, Duration? duration}) {
    var currentTime = DateTime.now().millisecondsSinceEpoch;
    // 相同消息持续时间内重复提交时,返回
    if (currentTime - _lastTime < _lastDuration * 1000 && _lastMessage == message) {
    return;
    }

    复制代码
     dismissSnackBar();
    
     Get.snackbar(
       title,
       message,
       backgroundColor: backgroundColor ?? Colors.black12,
       duration: duration ?? Duration(seconds: 2), // 提示框持续时间
       animationDuration: Duration(milliseconds: 0), // 过渡动画的时间,这里设置为0是为了在使用Get.dialog时避免关闭冲突
     );
    
     _lastDuration = duration?.inSeconds ?? 2;
     _lastTime = DateTime.now().millisecondsSinceEpoch;
     _lastMessage = message;

    }

    void dismissSnackBar() {
    Get.closeCurrentSnackbar();
    }
    }

这是一个避免重复显示的显示的提示框,可参考博客:Flutter中Get.snackbar避免重复显示的实现

  1. 创建一个LoadingDialog去实现加载框。

    import 'package:flutter/material.dart';
    import 'package:get/get.dart';
    import 'package:get/get_core/src/get_main.dart';

    class LoadingDialog {
    static void show([String? msg]) {
    Get.dialog(
    PopScope(
    canPop: false,
    child: Center(
    child: Container(
    padding: EdgeInsets.symmetric(horizontal: 24, vertical: 16), // 减小内边距
    decoration: BoxDecoration(
    color: Colors.white,
    borderRadius: BorderRadius.circular(8),
    ),
    child: Row(
    mainAxisSize: MainAxisSize.min, // 设置为最小宽度
    children: [
    SizedBox(
    width: 24, // 减小加载图标尺寸
    height: 24,
    child: CircularProgressIndicator(
    strokeWidth: 2.0, // 可以适当减小进度条宽度
    ),
    ),
    SizedBox(width: 12), // 减小间距
    Text(
    msg ?? "加载中...",
    style: TextStyle(fontSize: 14, color: Colors.black), // 可以适当调整字体大小
    ),
    ],
    ),
    ),
    ),
    ),
    barrierDismissible: false,
    );
    }

    static void hide() {
    if (Get.isDialogOpen ?? false) {
    // 先关闭 Snackbar
    Get.closeCurrentSnackbar();
    // 添加延迟以确保 Snackbar 已关闭
    Future.delayed(Duration(milliseconds: 100), () {
    if (Get.isDialogOpen ?? false) {
    Get.back();
    }
    });
    }
    }
    }

在关闭加载框之前,会先关闭提示框,由于Get.snackbar动画时长已经设置为0,此时延迟100ms后再关闭加载框是没有问题的。

相关推荐
fouryears_234178 小时前
Flutter InheritedWidget 详解:从生命周期到数据流动的完整解析
开发语言·flutter·客户端·dart
LinXunFeng13 小时前
Flutter - 详情页 TabBar 与模块联动?秒了!
前端·flutter·开源
阅文作家助手开发团队_山神17 小时前
第三章: 解决Android iPad蓝牙键盘联想词UI不跟随光标问题
flutter
阅文作家助手开发团队_山神17 小时前
第四章:Flutter自定义Engine本地依赖与打包流程
前端·flutter
程序员老刘17 小时前
Flutter 3.35 更新要点解析
flutter·ai编程·客户端
阅文作家助手开发团队_山神19 小时前
第一章: Mac Flutter Engine开发准备工作
前端·flutter
EmmaGuo201521 小时前
flutter3.7.12版本设置TextField的contextMenuBuilder的文字颜色
前端·flutter
鹏多多.1 天前
flutter-使用device_info_plus获取手机设备信息完整指南
android·前端·flutter·ios·数据分析·前端框架
来来走走1 天前
Flutter开发 网络请求
android·flutter
SoaringHeart2 天前
Flutter进阶:高内存任务的动态并发执行完美实现
前端·flutter