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后再关闭加载框是没有问题的。

相关推荐
ReyZhang2 小时前
flutter R库对图片资源进行自动管理
flutter
weixin_4111918421 小时前
Flutter中Get.snackbar避免重复显示的实现
flutter
奔跑的蚂蚁0121 小时前
Flutter插件制作、本地/远程依赖及缓存机制深入剖析(原创-附源码)
flutter
恋猫de小郭1 天前
深入 Flutter 和 Compose 在 UI 渲染刷新时 Diff 实现对比
flutter·ui
SEO-狼术1 天前
Syncfusion Essential Studio Flutter 2024 Crack
flutter
pengyu1 天前
系统化掌握Dart编程之面向对象基本概念
android·flutter·dart
sun_weitao3 天前
Flutter路由动画Hero函数的使用
java·服务器·flutter
ChinaDragonDreamer3 天前
Flutter:使用FVM安装多个Flutter SDK 版本和使用教程
flutter·鸿蒙