toast弹窗优化

This commit is contained in:
mmc
2026-03-03 10:28:50 +08:00
parent cf5415308a
commit 0a3a062c04
2 changed files with 226 additions and 30 deletions

173
lib/components/toast.dart Normal file
View File

@@ -0,0 +1,173 @@
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
// 自定义Toast工具类 - 气泡式提示
class ToastUtils {
static OverlayEntry? _overlayEntry;
static bool _isShowing = false;
/// 显示气泡提示
/// [context] 上下文
/// [message] 提示文本
/// [backgroundColor] 背景色
/// [duration] 显示时长
/// [positionTop] 距离顶部的高度
static void showToast(
BuildContext context,
String message, {
Color backgroundColor = const Color(0xCC333333),
Duration duration = const Duration(seconds: 1),
double positionTop = 80.0,
}) {
// 先关闭正在显示的提示
if (_isShowing) {
_overlayEntry?.remove();
_isShowing = false;
}
// 创建OverlayEntry
_overlayEntry = OverlayEntry(
builder: (BuildContext context) => Positioned(
top: positionTop,
left: MediaQuery.of(context).size.width * 0.1,
right: MediaQuery.of(context).size.width * 0.1,
child: Material(
color: Colors.transparent,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
decoration: BoxDecoration(
color: backgroundColor,
borderRadius: BorderRadius.circular(18),
boxShadow: [BoxShadow(color: Colors.black12, blurRadius: 10, offset: const Offset(0, 2))],
),
child: Text(
message,
textAlign: TextAlign.center,
style: const TextStyle(color: Colors.white, fontSize: 14, height: 1.2),
),
),
),
),
);
// 显示提示
SchedulerBinding.instance.addPostFrameCallback((_) {
Overlay.of(context).insert(_overlayEntry!);
_isShowing = true;
// 定时关闭
Future.delayed(duration, () {
if (_isShowing) {
_overlayEntry?.remove();
_isShowing = false;
}
});
});
}
/// 显示成功提示(绿色背景 + 85%不透明度)
static void showSuccess(BuildContext context, String message) {
showToast(
context,
message,
// 绿色:0xFF00C853 → 调整为 0xD900C853(D9=85%不透明度)
backgroundColor: const Color(0xD900C853),
duration: const Duration(seconds: 1),
);
}
/// 显示错误提示(红色背景 + 85%不透明度)
static void showError(BuildContext context, String message) {
showToast(
context,
message,
// 红色:0xFFFF5252 → 调整为 0xD9FF5252(D9=85%不透明度)
backgroundColor: const Color(0xD9FF5252),
duration: const Duration(seconds: 1),
);
}
/// 显示普通提示(灰色背景 + 80%不透明度)
static void showInfo(BuildContext context, String message) {
showToast(
context,
message,
// 灰色:0xCC333333 → 调整为 0xCC333333(保持80%,也可改为 0xB3333333=70%)
backgroundColor: const Color(0xCC333333),
duration: const Duration(seconds: 1),
);
}
/// 显示警告提示(黄色背景 + 85%不透明度)
static void showWarn(BuildContext context, String message) {
showToast(
context,
message,
// 黄色:0xFFFFC107 → 调整为 0xD9FFC107(D9=85%不透明度)
backgroundColor: const Color(0xD9FFC107),
duration: const Duration(seconds: 1),
);
}
/// 显示加载提示(蓝色背景 + 85%不透明度)
static void showLoading(BuildContext context, String message) {
showToast(
context,
message,
// 蓝色:0xFF0688D8 → 调整为 0xD90688D8(D9=85%不透明度)
backgroundColor: const Color(0xD90688D8),
duration: const Duration(seconds: 1),
);
}
// 扩展:支持自定义文字颜色
static void showToastWithTextColor(
BuildContext context,
String message, {
Color backgroundColor = const Color(0xCC333333),
Color textColor = Colors.white,
Duration duration = const Duration(seconds: 2),
double positionTop = 80.0,
}) {
if (_isShowing) {
_overlayEntry?.remove();
_isShowing = false;
}
_overlayEntry = OverlayEntry(
builder: (BuildContext context) => Positioned(
top: positionTop,
left: MediaQuery.of(context).size.width * 0.1,
right: MediaQuery.of(context).size.width * 0.1,
child: Material(
color: Colors.transparent,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
decoration: BoxDecoration(
color: backgroundColor,
borderRadius: BorderRadius.circular(24),
boxShadow: [BoxShadow(color: Colors.black12, blurRadius: 10, offset: const Offset(0, 2))],
),
child: Text(
message,
textAlign: TextAlign.center,
style: TextStyle(color: textColor, fontSize: 14, height: 1.2),
),
),
),
),
);
SchedulerBinding.instance.addPostFrameCallback((_) {
Overlay.of(context).insert(_overlayEntry!);
_isShowing = true;
Future.delayed(duration, () {
if (_isShowing) {
_overlayEntry?.remove();
_isShowing = false;
}
});
});
}
}