import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; class ObsToastWidget extends StatefulWidget { final String message; final VoidCallback? onDismiss; const ObsToastWidget({super.key, required this.message, this.onDismiss}); static OverlayEntry? _currentToast; static _ObsToastWidgetState? _currentState; // 显示 Toast static void show({required BuildContext context, required String message}) { dismiss(); _currentToast = OverlayEntry( builder: (context) => ObsToastWidget( message: message, onDismiss: () { _currentToast?.remove(); _currentToast = null; _currentState = null; }, ), ); Overlay.of(context).insert(_currentToast!); } // 主动消失(你要的) static void dismiss() { if (_currentState != null) { _currentState!._dismissToast(); } else if (_currentToast != null) { _currentToast!.remove(); _currentToast = null; } } @override State createState() => _ObsToastWidgetState(); } class _ObsToastWidgetState extends State with SingleTickerProviderStateMixin { late AnimationController _animationController; late Animation _fadeAnimation; @override void initState() { super.initState(); ObsToastWidget._currentState = this; _animationController = AnimationController(vsync: this, duration: const Duration(milliseconds: 300)); _fadeAnimation = Tween(begin: 0.0, end: 1.0).animate(CurvedAnimation(parent: _animationController, curve: Curves.easeInOut)); Future.delayed(const Duration(milliseconds: 50), () { if (mounted) _animationController.forward(); }); // 已删除:自动消失逻辑 } @override void dispose() { _animationController.dispose(); super.dispose(); } // 主动消失逻辑 void _dismissToast() { if (_animationController.status == AnimationStatus.completed) { _animationController.reverse().then((_) { widget.onDismiss?.call(); ObsToastWidget._currentState = null; }); } else { widget.onDismiss?.call(); ObsToastWidget._currentState = null; } } @override Widget build(BuildContext context) { return Positioned( // 定位:屏幕顶部居中(可根据需求调整) top: 100, left: MediaQuery.of(context).size.width * 0.1, right: MediaQuery.of(context).size.width * 0.1, child: FadeTransition( opacity: _fadeAnimation, child: Listener( child: GestureDetector( child: Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(8), boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.1), blurRadius: 10, offset: const Offset(0, 2))], ), child: Row( mainAxisSize: MainAxisSize.min, children: [ // SVG 图标(替换为你的 SVG 路径/字符串) SvgPicture.string( ''' ''', width: 32, height: 32, ), const SizedBox(width: 8), // 图标和文字间距 // 提示文字 Text(widget.message, style: const TextStyle(fontSize: 14, color: Colors.black87)), ], ), ), ), ), ), ); } }