- 新增 OfflineBanner widget: 监听 connectivity_plus 自动显示/隐藏 - AnimatedCrossFade 滑入滑出动画 + warmCurve 弹性曲线 - 黄色警告条: wifi_off 图标 + '网络不可用,部分功能受限' - 嵌入 ResponsiveScaffold 的 body 上方 (手机/平板/桌面三端) - 只在离线时显示,恢复网络后自动消失
103 lines
2.8 KiB
Dart
103 lines
2.8 KiB
Dart
// 全局离线提示横幅 — 监听 connectivity_plus 显示/隐藏
|
|
//
|
|
// 放在 Scaffold body 上方,离线时显示黄色警告横幅
|
|
// 使用: 在 responsive_scaffold 的 body 上方嵌套
|
|
|
|
import 'package:connectivity_plus/connectivity_plus.dart';
|
|
import 'package:flutter/material.dart';
|
|
|
|
import '../core/constants/design_tokens.dart';
|
|
import '../core/theme/app_colors.dart';
|
|
|
|
/// 全局离线提示横幅 — 自动监听网络状态
|
|
class OfflineBanner extends StatefulWidget {
|
|
const OfflineBanner({super.key, required this.child});
|
|
|
|
final Widget child;
|
|
|
|
@override
|
|
State<OfflineBanner> createState() => _OfflineBannerState();
|
|
}
|
|
|
|
class _OfflineBannerState extends State<OfflineBanner> {
|
|
bool _isOffline = false;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
// 初始检查
|
|
Connectivity().checkConnectivity().then((result) {
|
|
if (mounted) {
|
|
setState(() {
|
|
_isOffline = result.every((r) => r == ConnectivityResult.none);
|
|
});
|
|
}
|
|
});
|
|
// 监听变化
|
|
Connectivity().onConnectivityChanged.listen((result) {
|
|
if (mounted) {
|
|
final offline = result.every((r) => r == ConnectivityResult.none);
|
|
if (offline != _isOffline) {
|
|
setState(() => _isOffline = offline);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Column(
|
|
children: [
|
|
// 离线横幅 — 带动画滑入/滑出
|
|
AnimatedCrossFade(
|
|
firstChild: const SizedBox.shrink(),
|
|
secondChild: _OfflineBar(),
|
|
crossFadeState: _isOffline
|
|
? CrossFadeState.showSecond
|
|
: CrossFadeState.showFirst,
|
|
duration: DesignTokens.animNormal,
|
|
sizeCurve: DesignTokens.warmCurve,
|
|
),
|
|
// 正常内容
|
|
Expanded(child: widget.child),
|
|
],
|
|
);
|
|
}
|
|
}
|
|
|
|
/// 离线横幅条
|
|
class _OfflineBar extends StatelessWidget {
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Container(
|
|
width: double.infinity,
|
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
|
decoration: BoxDecoration(
|
|
color: AppColors.warning.withValues(alpha: 0.15),
|
|
border: Border(
|
|
bottom: BorderSide(
|
|
color: AppColors.warning.withValues(alpha: 0.3),
|
|
width: 1,
|
|
),
|
|
),
|
|
),
|
|
child: Row(
|
|
children: [
|
|
Icon(Icons.wifi_off_rounded, size: 16, color: AppColors.warning),
|
|
const SizedBox(width: 8),
|
|
Expanded(
|
|
child: Text(
|
|
'网络不可用,部分功能受限',
|
|
style: TextStyle(
|
|
fontSize: 13,
|
|
color: AppColors.warning,
|
|
fontWeight: FontWeight.w500,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|