1111
This commit is contained in:
parent
f7d44c9a34
commit
98cdfe7fb6
|
|
@ -518,51 +518,101 @@ class AppUpgradeSimple {
|
|||
);
|
||||
}
|
||||
|
||||
/// 使用 Overlay 显示 Toast(不依赖 Scaffold)
|
||||
void _showOverlayToast(BuildContext context, String message, UpgradeConfig config) {
|
||||
if (!context.mounted) {
|
||||
debugPrint('Toast消息(context已卸载): $message');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
final overlay = Overlay.of(context);
|
||||
|
||||
// 创建 OverlayEntry
|
||||
final overlayEntry = OverlayEntry(
|
||||
builder: (context) => _ToastWidget(message: message),
|
||||
);
|
||||
|
||||
// 插入到 Overlay
|
||||
overlay.insert(overlayEntry);
|
||||
|
||||
// 2秒后自动移除
|
||||
Future.delayed(const Duration(seconds: 2), () {
|
||||
try {
|
||||
overlayEntry.remove();
|
||||
} catch (e) {
|
||||
// 忽略移除错误
|
||||
if (config.enableDebugLog) {
|
||||
debugPrint('移除Toast失败: $e');
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
debugPrint('显示Toast失败: $e');
|
||||
debugPrint('Toast消息: $message');
|
||||
}
|
||||
}
|
||||
|
||||
/// 尝试使用 ScaffoldMessenger 显示 SnackBar(如果可用)
|
||||
void _tryShowSnackBar(BuildContext context, String message, UpgradeConfig config) {
|
||||
if (!context.mounted) {
|
||||
_showOverlayToast(context, message, config);
|
||||
return;
|
||||
}
|
||||
|
||||
// 尝试获取 ScaffoldMessenger
|
||||
final scaffoldMessenger = ScaffoldMessenger.maybeOf(context);
|
||||
if (scaffoldMessenger == null) {
|
||||
// 如果没有 ScaffoldMessenger,使用 Overlay Toast
|
||||
_showOverlayToast(context, message, config);
|
||||
return;
|
||||
}
|
||||
|
||||
// 尝试使用根 Navigator 的 context(更安全)
|
||||
BuildContext? rootContext;
|
||||
try {
|
||||
final navigator = Navigator.maybeOf(context, rootNavigator: true);
|
||||
if (navigator != null) {
|
||||
rootContext = navigator.context;
|
||||
}
|
||||
} catch (e) {
|
||||
// 忽略错误,继续使用原 context
|
||||
}
|
||||
|
||||
// 优先使用根 context 的 ScaffoldMessenger
|
||||
final messenger =
|
||||
rootContext != null && rootContext.mounted ? ScaffoldMessenger.maybeOf(rootContext) : scaffoldMessenger;
|
||||
|
||||
if (messenger == null) {
|
||||
_showOverlayToast(context, message, config);
|
||||
return;
|
||||
}
|
||||
|
||||
// 尝试显示 SnackBar,如果失败则使用 Overlay Toast
|
||||
try {
|
||||
messenger.showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(message),
|
||||
duration: Duration(seconds: 2),
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
// 如果 SnackBar 失败,使用 Overlay Toast
|
||||
if (config.enableDebugLog) {
|
||||
debugPrint('SnackBar显示失败,使用Overlay Toast: $e');
|
||||
}
|
||||
_showOverlayToast(context, message, config);
|
||||
}
|
||||
}
|
||||
|
||||
/// 显示Toast提示
|
||||
void _showToast(String message, BuildContext context, [UpgradeConfig? config]) {
|
||||
final effectiveConfig = config ?? _config;
|
||||
if (effectiveConfig.customToast != null) {
|
||||
effectiveConfig.customToast!(message);
|
||||
} else {
|
||||
// 检查 context 是否有效
|
||||
if (!context.mounted) {
|
||||
debugPrint('Toast消息(context已卸载): $message');
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查是否有 Scaffold 在 widget 树中
|
||||
final scaffold = Scaffold.maybeOf(context);
|
||||
if (scaffold == null) {
|
||||
// 如果没有 Scaffold,使用 debugPrint 作为后备方案
|
||||
debugPrint('Toast消息(无Scaffold): $message');
|
||||
return;
|
||||
}
|
||||
|
||||
// 使用 maybeOf 安全地获取 ScaffoldMessenger
|
||||
final scaffoldMessenger = ScaffoldMessenger.maybeOf(context);
|
||||
if (scaffoldMessenger == null) {
|
||||
// 如果没有 ScaffoldMessenger,使用 debugPrint 作为后备方案
|
||||
debugPrint('Toast消息(无ScaffoldMessenger): $message');
|
||||
return;
|
||||
}
|
||||
|
||||
// 即使有 Scaffold 和 ScaffoldMessenger,也可能出现其他问题
|
||||
// 使用 try-catch 捕获所有可能的错误
|
||||
try {
|
||||
scaffoldMessenger.showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(message),
|
||||
duration: Duration(seconds: 2),
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
// 捕获所有错误,包括断言错误
|
||||
// 在调试模式下,断言错误可能仍然会显示,但不会导致应用崩溃
|
||||
debugPrint('显示Toast失败(已使用后备方案): $message');
|
||||
if (effectiveConfig.enableDebugLog) {
|
||||
debugPrint('错误详情: $e');
|
||||
}
|
||||
}
|
||||
// 优先尝试使用 SnackBar,如果失败则使用 Overlay Toast
|
||||
_tryShowSnackBar(context, message, effectiveConfig);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2053,3 +2103,68 @@ class _ForceUpgradeDialogState extends State<_ForceUpgradeDialog> with _UpgradeD
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 使用 Overlay 显示的 Toast Widget(不依赖 Scaffold)
|
||||
class _ToastWidget extends StatelessWidget {
|
||||
final String message;
|
||||
|
||||
const _ToastWidget({required this.message});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Positioned(
|
||||
top: MediaQuery.of(context).padding.top + 16,
|
||||
left: 16,
|
||||
right: 16,
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
child: SafeArea(
|
||||
child: IgnorePointer(
|
||||
child: TweenAnimationBuilder<double>(
|
||||
duration: const Duration(milliseconds: 300),
|
||||
tween: Tween(begin: 0.0, end: 1.0),
|
||||
builder: (context, value, child) {
|
||||
return Opacity(
|
||||
opacity: value,
|
||||
child: Transform.translate(
|
||||
offset: Offset(0, -20 * (1 - value)),
|
||||
child: child,
|
||||
),
|
||||
);
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.black87,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.2),
|
||||
blurRadius: 8,
|
||||
offset: const Offset(0, 4),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Flexible(
|
||||
child: Text(
|
||||
message,
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 14,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue