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

ops/2025/1/16 15:04:43/

背景:
在使用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避免重复显示的实现
2. 创建一个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) {// 先关闭 SnackbarGet.closeCurrentSnackbar();// 添加延迟以确保 Snackbar 已关闭Future.delayed(Duration(milliseconds: 100), () {if (Get.isDialogOpen ?? false) {Get.back();}});}}
}

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

方案二

  1. 通过源码可以看出,在调用Get.back()方法时,默认传参closeOverlays为false,closeOverlays参数表示是否关闭所有覆盖层,覆盖层包括对话框、Snackbar、底部弹出框等,isSnackbarOpen为是否存在Snakbar,默认状态下,存在Snackbar时,会执行closeCurrentSnackbar()并retrun。
  void back<T>({T? result,bool closeOverlays = false,bool canPop = true,int? id,}) {//TODO: This code brings compatibility of the new snackbar with GetX 4,// remove this code in version 5if (isSnackbarOpen && !closeOverlays) {closeCurrentSnackbar();return;}if (closeOverlays && isOverlaysOpen) {//TODO: This code brings compatibility of the new snackbar with GetX 4,// remove this code in version 5if (isSnackbarOpen) {closeAllSnackbars();}navigator?.popUntil((route) {return (!isDialogOpen! && !isBottomSheetOpen!);});}if (canPop) {if (global(id).currentState?.canPop() == true) {global(id).currentState?.pop<T>(result);}} else {global(id).currentState?.pop<T>(result);}}
  1. 知道原因后就简单了,我们只需将closeOverlays传参为true则可完美解决冲突问题。
    if (Get.isDialogOpen ?? false) {Get.back(closeOverlays: true);}

http://www.ppmy.cn/ops/150582.html

相关文章

8.User-Agnet代理池

在编写爬虫程序时&#xff0c;一般都会构建一个 User-Agent &#xff08;用户代理&#xff09;池&#xff0c;就是把多个浏览器的 UA 信息放进列表中&#xff0c;然后再从中随机选择。构建用户代理池&#xff0c;能够避免总是使用一个 UA 来访问网站&#xff0c;因为短时间内总…

Linux根据Sql文件导入Mysql数据库

在Linux环境下&#xff0c;根据SQL文件导入MySQL数据库可以按照以下步骤进行&#xff1a; 1. 确保MySQL服务正在运行 首先&#xff0c;确保MySQL服务正在运行。你可以使用以下命令来检查MySQL服务的状态&#xff08;以Ubuntu为例&#xff09;&#xff1a; sudo systemctl st…

【Vim Masterclass 笔记12】S06L26 + L27:Vim 文本的搜索、查找及替换同步练习(含点评课)

文章目录 S06L26 Exercise 07 - Search, Find, and Replace1 训练目标2 操作指令2.1. 打开 search-practice.txt 文件2.2. 同一行内的搜索练习2.3. 当前文件内的搜索练习2.4. 单词搜索练习2.5. 全局替换练习 3 退出 Vim S06L27 同步练习点评课 写在前面 Vim 的文本检索、查找与…

【Rust自学】12.7. 使用环境变量

12.7.0. 写在正文之前 第12章要做一个实例的项目——一个命令行程序。这个程序是一个grep(Global Regular Expression Print)&#xff0c;是一个全局正则搜索和输出的工具。它的功能是在指定的文件中搜索出指定的文字。 这个项目分为这么几步&#xff1a; 接收命令行参数读取…

机器学习(1):线性回归概念

1 线性回归基础 1.1 什么是线性 例如&#xff1a;汽车每小时60KM&#xff0c;3小时可以行使多长距离&#xff1f;已知汽车的速度&#xff0c;则汽车的行使距离只与时间唯一相关。在二元的直角坐标系中&#xff0c;描出这一关系的图是一条直线&#xff0c;所以称为线性关系。 线…

炸砖块游戏的最终图案

描述 小红正在玩一个“炸砖块”游戏,游戏的规则如下:初始有一个 n * m 的砖块矩阵。小红会炸 k 次,每次会向一个位置投炸弹,如果这个位置有一个砖块,则砖块消失,上方的砖块向下落。小红希望你画出最终砖块的图案。 输入描述 第一行输入三个正整数 n, m, k,代表矩阵的行…

python创建pdf水印,希望根据文本长度调整水印字体大小,避免超出页面

为了根据文本长度动态调整水印字体大小&#xff0c;可以先测量文本长度&#xff0c;然后根据页面宽度和高度动态计算合适的字体大小。以下是修改后的代码&#xff1a; from reportlab.pdfgen import canvas from reportlab.lib.pagesizes import letter from reportlab.pdfbas…

Unity3D 移动端CPU端性能调优详解

前言 在Unity3D开发中&#xff0c;特别是在移动端&#xff0c;性能优化至关重要。CPU主要负责逻辑运算、物理计算和碰撞检测等核心任务。优化CPU性能不仅能提升游戏的流畅度&#xff0c;还能减少电量消耗和发热问题。本文将详细介绍Unity3D移动端CPU端的性能调优技术&#xff…