Files
AutoTime-Tracker/lib/widgets/empty_state_widget.dart
2025-11-13 15:45:28 +08:00

150 lines
4.2 KiB
Dart

import 'package:flutter/material.dart';
import '../theme/app_theme.dart';
/// 空状态组件
/// 用于显示无数据时的友好提示
class EmptyStateWidget extends StatelessWidget {
final IconData icon;
final String title;
final String? subtitle;
final String? actionLabel;
final VoidCallback? onAction;
final bool showIllustration;
const EmptyStateWidget({
super.key,
required this.icon,
required this.title,
this.subtitle,
this.actionLabel,
this.onAction,
this.showIllustration = true,
});
/// 默认空状态 - 无数据
factory EmptyStateWidget.noData({
String? title,
String? subtitle,
String? actionLabel,
VoidCallback? onAction,
}) {
return EmptyStateWidget(
icon: Icons.inbox_outlined,
title: title ?? '暂无数据',
subtitle: subtitle ?? '使用应用一段时间后,数据将显示在这里',
actionLabel: actionLabel,
onAction: onAction,
);
}
/// 空状态 - 无搜索结果
factory EmptyStateWidget.noSearchResults({
String? query,
}) {
return EmptyStateWidget(
icon: Icons.search_off,
title: '未找到匹配结果',
subtitle: query != null ? '没有找到与 "$query" 相关的内容' : '请尝试其他关键词',
showIllustration: false,
);
}
/// 空状态 - 无应用数据
factory EmptyStateWidget.noApps({
VoidCallback? onAction,
}) {
return EmptyStateWidget(
icon: Icons.apps_outlined,
title: '暂无应用数据',
subtitle: '使用应用一段时间后,应用使用记录将显示在这里',
actionLabel: '刷新',
onAction: onAction,
);
}
/// 空状态 - 首次使用
factory EmptyStateWidget.firstTime({
VoidCallback? onAction,
}) {
return EmptyStateWidget(
icon: Icons.touch_app,
title: '欢迎使用 AutoTime Tracker',
subtitle: '开始追踪您的时间使用情况\n\n1. 授予应用使用权限\n2. 正常使用您的设备\n3. 查看详细的使用统计',
actionLabel: '去设置权限',
onAction: onAction,
);
}
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Center(
child: Padding(
padding: const EdgeInsets.all(32),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (showIllustration) ...[
Container(
width: 120,
height: 120,
decoration: BoxDecoration(
color: AppTheme.primaryColor.withOpacity(0.1),
shape: BoxShape.circle,
),
child: Icon(
icon,
size: 64,
color: AppTheme.primaryColor.withOpacity(0.6),
),
),
const SizedBox(height: 24),
] else ...[
Icon(
icon,
size: 64,
color: theme.colorScheme.onSurface.withOpacity(0.3),
),
const SizedBox(height: 16),
],
Text(
title,
style: theme.textTheme.titleLarge?.copyWith(
fontWeight: FontWeight.w600,
color: theme.colorScheme.onSurface,
),
textAlign: TextAlign.center,
),
if (subtitle != null) ...[
const SizedBox(height: 12),
Text(
subtitle!,
style: theme.textTheme.bodyMedium?.copyWith(
color: theme.colorScheme.onSurface.withOpacity(0.6),
),
textAlign: TextAlign.center,
),
],
if (actionLabel != null && onAction != null) ...[
const SizedBox(height: 24),
ElevatedButton.icon(
onPressed: onAction,
icon: const Icon(Icons.refresh),
label: Text(actionLabel!),
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(
horizontal: 24,
vertical: 12,
),
),
),
],
],
),
),
);
}
}