Files
xianyan/lib/features/mine/settings/presentation/theme/theme_shared_widgets.dart
Developer fed86c0375 迁移
2026-05-21 04:27:21 +08:00

106 lines
3.1 KiB
Dart

/// ============================================================
/// 闲言APP — 主题设置共享组件
/// 创建时间: 2026-05-19
/// 更新时间: 2026-05-19
/// 作用: 主题设置页面中复用的 SectionHeader 和 OptionChip 组件
/// 上次更新: 从 theme_settings_page.dart 拆分出共享组件
/// ============================================================
import 'package:flutter/cupertino.dart';
import '../../../../../../core/theme/app_radius.dart';
import '../../../../../../core/theme/app_spacing.dart';
import '../../../../../../core/theme/app_theme.dart';
import '../../../../../../core/theme/app_typography.dart';
/// 主题设置分组标题
class ThemeSectionHeader extends StatelessWidget {
const ThemeSectionHeader({super.key, required this.icon, required this.title});
final IconData icon;
final String title;
@override
Widget build(BuildContext context) {
final ext = AppTheme.ext(context);
return Row(
children: [
Icon(icon, size: 16, color: ext.accent),
const SizedBox(width: 6),
Text(
title,
style: AppTypography.subhead.copyWith(
color: ext.textPrimary,
fontWeight: FontWeight.w600,
),
),
],
);
}
}
/// 主题设置选项芯片
class ThemeOptionChip extends StatelessWidget {
const ThemeOptionChip({
super.key,
required this.label,
required this.isSelected,
required this.onTap,
this.icon,
});
final String label;
final bool isSelected;
final VoidCallback onTap;
final IconData? icon;
@override
Widget build(BuildContext context) {
final ext = AppTheme.ext(context);
return Expanded(
child: GestureDetector(
onTap: onTap,
child: AnimatedContainer(
duration: const Duration(milliseconds: 200),
curve: Curves.easeOutCubic,
margin: const EdgeInsets.symmetric(horizontal: 2),
padding: const EdgeInsets.symmetric(vertical: AppSpacing.sm),
decoration: BoxDecoration(
color: isSelected
? ext.accent.withValues(alpha: 0.15)
: ext.bgSecondary,
borderRadius: AppRadius.of(context).mdBorder,
border: isSelected
? Border.all(color: ext.accent, width: 1.5)
: null,
),
child: Center(
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
if (icon != null) ...[
Icon(
icon,
size: 14,
color: isSelected ? ext.accent : ext.textSecondary,
),
const SizedBox(width: 4),
],
Text(
label,
style: AppTypography.subhead.copyWith(
color: isSelected ? ext.accent : ext.textSecondary,
fontWeight: isSelected
? FontWeight.w600
: FontWeight.normal,
),
),
],
),
),
),
),
);
}
}