356 lines
13 KiB
Dart
356 lines
13 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter/services.dart';
|
|
|
|
/// 应用主题配置类 - 管理应用的主题样式和色彩方案
|
|
/// 支持浅色主题、深色主题和系统跟随模式
|
|
class AppTheme {
|
|
// 私有构造函数,防止实例化
|
|
AppTheme._();
|
|
|
|
/// 主题色彩配置
|
|
static const Color primaryColor = Color(0xFF2196F3);
|
|
static const Color secondaryColor = Color(0xFF03DAC6);
|
|
static const Color backgroundColor = Color(0xFFF5F5F5);
|
|
static const Color surfaceColor = Colors.white;
|
|
static const Color errorColor = Color(0xFFB00020);
|
|
|
|
/// 文字颜色
|
|
static const Color textPrimary = Color(0xFF212121);
|
|
static const Color textSecondary = Color(0xFF757575);
|
|
static const Color textHint = Color(0xFFBDBDBD);
|
|
|
|
/// 边框和分割线颜色
|
|
static const Color dividerColor = Color(0xFFE0E0E0);
|
|
static const Color borderColor = Color(0xFFCCCCCC);
|
|
|
|
/// 浅色主题
|
|
static ThemeData lightTheme = ThemeData(
|
|
useMaterial3: true,
|
|
brightness: Brightness.light,
|
|
primaryColor: primaryColor,
|
|
colorScheme: const ColorScheme.light(
|
|
primary: primaryColor,
|
|
secondary: secondaryColor,
|
|
surface: surfaceColor,
|
|
background: backgroundColor,
|
|
error: errorColor,
|
|
onPrimary: Colors.white,
|
|
onSecondary: Colors.black,
|
|
onSurface: textPrimary,
|
|
onBackground: textPrimary,
|
|
onError: Colors.white,
|
|
),
|
|
|
|
// 应用栏主题
|
|
appBarTheme: const AppBarTheme(
|
|
backgroundColor: surfaceColor,
|
|
foregroundColor: textPrimary,
|
|
elevation: 0,
|
|
centerTitle: true,
|
|
systemOverlayStyle: SystemUiOverlayStyle(
|
|
statusBarColor: Colors.transparent,
|
|
statusBarIconBrightness: Brightness.dark,
|
|
statusBarBrightness: Brightness.light,
|
|
),
|
|
),
|
|
|
|
// 卡片主题
|
|
cardTheme: CardTheme(
|
|
elevation: 2,
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(8.0),
|
|
),
|
|
margin: const EdgeInsets.all(8.0),
|
|
),
|
|
|
|
// 按钮主题
|
|
elevatedButtonTheme: ElevatedButtonThemeData(
|
|
style: ElevatedButton.styleFrom(
|
|
elevation: 2,
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(8.0),
|
|
),
|
|
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 12.0),
|
|
),
|
|
),
|
|
|
|
// 输入框主题
|
|
inputDecorationTheme: InputDecorationTheme(
|
|
filled: true,
|
|
fillColor: Colors.grey[100],
|
|
border: OutlineInputBorder(
|
|
borderRadius: BorderRadius.circular(8.0),
|
|
borderSide: const BorderSide(color: borderColor),
|
|
),
|
|
enabledBorder: OutlineInputBorder(
|
|
borderRadius: BorderRadius.circular(8.0),
|
|
borderSide: const BorderSide(color: borderColor),
|
|
),
|
|
focusedBorder: OutlineInputBorder(
|
|
borderRadius: BorderRadius.circular(8.0),
|
|
borderSide: const BorderSide(color: primaryColor, width: 2.0),
|
|
),
|
|
contentPadding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 12.0),
|
|
),
|
|
|
|
// 文字主题
|
|
textTheme: const TextTheme(
|
|
displayLarge: TextStyle(fontSize: 57.0, fontWeight: FontWeight.w400, color: textPrimary),
|
|
displayMedium: TextStyle(fontSize: 45.0, fontWeight: FontWeight.w400, color: textPrimary),
|
|
displaySmall: TextStyle(fontSize: 36.0, fontWeight: FontWeight.w400, color: textPrimary),
|
|
headlineLarge: TextStyle(fontSize: 32.0, fontWeight: FontWeight.w400, color: textPrimary),
|
|
headlineMedium: TextStyle(fontSize: 28.0, fontWeight: FontWeight.w400, color: textPrimary),
|
|
headlineSmall: TextStyle(fontSize: 24.0, fontWeight: FontWeight.w400, color: textPrimary),
|
|
titleLarge: TextStyle(fontSize: 22.0, fontWeight: FontWeight.w400, color: textPrimary),
|
|
titleMedium: TextStyle(fontSize: 16.0, fontWeight: FontWeight.w500, color: textPrimary),
|
|
titleSmall: TextStyle(fontSize: 14.0, fontWeight: FontWeight.w500, color: textPrimary),
|
|
bodyLarge: TextStyle(fontSize: 16.0, fontWeight: FontWeight.w400, color: textPrimary),
|
|
bodyMedium: TextStyle(fontSize: 14.0, fontWeight: FontWeight.w400, color: textPrimary),
|
|
bodySmall: TextStyle(fontSize: 12.0, fontWeight: FontWeight.w400, color: textSecondary),
|
|
labelLarge: TextStyle(fontSize: 14.0, fontWeight: FontWeight.w500, color: textPrimary),
|
|
labelMedium: TextStyle(fontSize: 12.0, fontWeight: FontWeight.w500, color: textPrimary),
|
|
labelSmall: TextStyle(fontSize: 11.0, fontWeight: FontWeight.w500, color: textPrimary),
|
|
),
|
|
|
|
// 图标主题
|
|
iconTheme: const IconThemeData(
|
|
color: textSecondary,
|
|
size: 24.0,
|
|
),
|
|
|
|
// 分割线主题
|
|
dividerTheme: const DividerThemeData(
|
|
color: dividerColor,
|
|
thickness: 1.0,
|
|
space: 0,
|
|
),
|
|
);
|
|
|
|
/// 深色主题
|
|
static ThemeData darkTheme = ThemeData(
|
|
useMaterial3: true,
|
|
brightness: Brightness.dark,
|
|
primaryColor: primaryColor,
|
|
colorScheme: const ColorScheme.dark(
|
|
primary: primaryColor,
|
|
secondary: secondaryColor,
|
|
surface: Color(0xFF121212),
|
|
background: Color(0xFF121212),
|
|
error: errorColor,
|
|
onPrimary: Colors.white,
|
|
onSecondary: Colors.black,
|
|
onSurface: Colors.white,
|
|
onBackground: Colors.white,
|
|
onError: Colors.white,
|
|
),
|
|
|
|
// 应用栏主题(深色模式保持一定对比度)
|
|
appBarTheme: const AppBarTheme(
|
|
backgroundColor: Color(0xFF1E1E1E),
|
|
foregroundColor: Colors.white,
|
|
elevation: 0,
|
|
centerTitle: true,
|
|
systemOverlayStyle: SystemUiOverlayStyle(
|
|
statusBarColor: Colors.transparent,
|
|
statusBarIconBrightness: Brightness.light,
|
|
statusBarBrightness: Brightness.dark,
|
|
),
|
|
),
|
|
|
|
// 卡片主题
|
|
cardTheme: CardTheme(
|
|
elevation: 4,
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(8.0),
|
|
),
|
|
margin: const EdgeInsets.all(8.0),
|
|
color: const Color(0xFF1E1E1E),
|
|
),
|
|
|
|
// 按钮主题
|
|
elevatedButtonTheme: ElevatedButtonThemeData(
|
|
style: ElevatedButton.styleFrom(
|
|
elevation: 2,
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(8.0),
|
|
),
|
|
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 12.0),
|
|
backgroundColor: primaryColor,
|
|
foregroundColor: Colors.white,
|
|
),
|
|
),
|
|
|
|
// 输入框主题
|
|
inputDecorationTheme: InputDecorationTheme(
|
|
filled: true,
|
|
fillColor: const Color(0xFF2C2C2C),
|
|
border: OutlineInputBorder(
|
|
borderRadius: BorderRadius.circular(8.0),
|
|
borderSide: const BorderSide(color: Color(0xFF3C3C3C)),
|
|
),
|
|
enabledBorder: OutlineInputBorder(
|
|
borderRadius: BorderRadius.circular(8.0),
|
|
borderSide: const BorderSide(color: Color(0xFF3C3C3C)),
|
|
),
|
|
focusedBorder: OutlineInputBorder(
|
|
borderRadius: BorderRadius.circular(8.0),
|
|
borderSide: const BorderSide(color: primaryColor, width: 2.0),
|
|
),
|
|
contentPadding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 12.0),
|
|
),
|
|
|
|
// 文字主题(深色模式保持可读性)
|
|
textTheme: const TextTheme(
|
|
displayLarge: TextStyle(fontSize: 57.0, fontWeight: FontWeight.w400, color: Colors.white),
|
|
displayMedium: TextStyle(fontSize: 45.0, fontWeight: FontWeight.w400, color: Colors.white),
|
|
displaySmall: TextStyle(fontSize: 36.0, fontWeight: FontWeight.w400, color: Colors.white),
|
|
headlineLarge: TextStyle(fontSize: 32.0, fontWeight: FontWeight.w400, color: Colors.white),
|
|
headlineMedium: TextStyle(fontSize: 28.0, fontWeight: FontWeight.w400, color: Colors.white),
|
|
headlineSmall: TextStyle(fontSize: 24.0, fontWeight: FontWeight.w400, color: Colors.white),
|
|
titleLarge: TextStyle(fontSize: 22.0, fontWeight: FontWeight.w400, color: Colors.white),
|
|
titleMedium: TextStyle(fontSize: 16.0, fontWeight: FontWeight.w500, color: Colors.white),
|
|
titleSmall: TextStyle(fontSize: 14.0, fontWeight: FontWeight.w500, color: Colors.white),
|
|
bodyLarge: TextStyle(fontSize: 16.0, fontWeight: FontWeight.w400, color: Colors.white),
|
|
bodyMedium: TextStyle(fontSize: 14.0, fontWeight: FontWeight.w400, color: Colors.white),
|
|
bodySmall: TextStyle(fontSize: 12.0, fontWeight: FontWeight.w400, color: Color(0xFFB0B0B0)),
|
|
labelLarge: TextStyle(fontSize: 14.0, fontWeight: FontWeight.w500, color: Colors.white),
|
|
labelMedium: TextStyle(fontSize: 12.0, fontWeight: FontWeight.w500, color: Colors.white),
|
|
labelSmall: TextStyle(fontSize: 11.0, fontWeight: FontWeight.w500, color: Colors.white),
|
|
),
|
|
|
|
// 图标主题
|
|
iconTheme: const IconThemeData(
|
|
color: Color(0xFFB0B0B0),
|
|
size: 24.0,
|
|
),
|
|
|
|
// 分割线主题
|
|
dividerTheme: const DividerThemeData(
|
|
color: Color(0xFF3C3C3C),
|
|
thickness: 1.0,
|
|
space: 0,
|
|
),
|
|
);
|
|
|
|
/// 获取主题模式对应的主题数据
|
|
static ThemeData getTheme(Brightness brightness) {
|
|
return brightness == Brightness.dark ? darkTheme : lightTheme;
|
|
}
|
|
|
|
/// 获取当前主题的对比色(用于保证可读性)
|
|
static Color getContrastColor(Color backgroundColor) {
|
|
// 计算颜色的亮度
|
|
final brightness = backgroundColor.computeLuminance();
|
|
// 亮度大于0.5使用深色,否则使用浅色
|
|
return brightness > 0.5 ? Colors.black : Colors.white;
|
|
}
|
|
}
|
|
|
|
/// 应用色彩配置类 - 定义应用使用的颜色常量
|
|
/// 提供浅色和深色主题下的颜色配置
|
|
class AppColors {
|
|
/// 主色调 - 应用的主要品牌色彩
|
|
static const Color primary = Color(0xFF2196F3);
|
|
|
|
/// 主色调上的文本色彩 - 用于主色调背景上的文本
|
|
static const Color onPrimary = Color(0xFFFFFFFF);
|
|
|
|
/// 次要色调 - 用于次要操作或强调
|
|
static const Color secondary = Color(0xFF03DAC6);
|
|
|
|
/// 次要色调上的文本色彩 - 用于次要色调背景上的文本
|
|
static const Color onSecondary = Color(0xFF000000);
|
|
|
|
/// 错误色调 - 用于错误提示、危险操作等
|
|
static const Color error = Color(0xFFB00020);
|
|
|
|
/// 错误色调上的文本色彩 - 用于错误色调背景上的文本
|
|
static const Color onError = Color(0xFFFFFFFF);
|
|
|
|
/// 背景色彩 - 应用的主要背景色
|
|
static const Color background = Color(0xFFF5F5F5);
|
|
|
|
/// 背景上的文本色彩 - 用于背景上的主要文本
|
|
static const Color onBackground = Color(0xFF212121);
|
|
|
|
/// 表面色彩 - 卡片、对话框等组件的背景色
|
|
static const Color surface = Color(0xFFFFFFFF);
|
|
|
|
/// 表面上的文本色彩 - 用于表面上的主要文本
|
|
static const Color onSurface = Color(0xFF212121);
|
|
|
|
/// 表面变体色彩 - 用于区分不同层次的表面
|
|
static const Color surfaceVariant = Color(0xFFE0E0E0);
|
|
|
|
/// 表面变体上的文本色彩 - 用于表面变体上的文本
|
|
static const Color onSurfaceVariant = Color(0xFF616161);
|
|
|
|
/// 轮廓色彩 - 用于边框、分割线等
|
|
static const Color outline = Color(0xFFBDBDBD);
|
|
|
|
/// 成功色彩 - 用于成功提示、完成状态等
|
|
static const Color success = Color(0xFF4CAF50);
|
|
|
|
/// 警告色彩 - 用于警告提示、注意状态等
|
|
static const Color warning = Color(0xFFFF9800);
|
|
|
|
/// 信息色彩 - 用于信息提示、说明状态等
|
|
static const Color info = Color(0xFF2196F3);
|
|
|
|
/// 禁用状态色彩 - 用于禁用状态的组件
|
|
static const Color disabled = Color(0xFFBDBDBD);
|
|
|
|
/// 加载状态色彩 - 用于加载指示器
|
|
static const Color loading = Color(0xFF2196F3);
|
|
|
|
/// 透明色彩 - 用于需要透明的场景
|
|
static const Color transparent = Color(0x00000000);
|
|
|
|
/// 阴影色彩 - 用于阴影效果
|
|
static const Color shadow = Color(0x1F000000);
|
|
|
|
/// 从BuildContext获取颜色配置 - 便捷方法获取当前主题颜色
|
|
static AppColors of(BuildContext context) {
|
|
// 这里可以根据主题亮度返回不同的颜色配置
|
|
// 目前返回默认的颜色配置
|
|
return AppColors();
|
|
}
|
|
|
|
/// 创建浅色主题颜色方案
|
|
static ColorScheme get lightColorScheme {
|
|
return const ColorScheme.light(
|
|
primary: primary,
|
|
onPrimary: onPrimary,
|
|
secondary: secondary,
|
|
onSecondary: onSecondary,
|
|
error: error,
|
|
onError: onError,
|
|
background: background,
|
|
onBackground: onBackground,
|
|
surface: surface,
|
|
onSurface: onSurface,
|
|
surfaceVariant: surfaceVariant,
|
|
onSurfaceVariant: onSurfaceVariant,
|
|
outline: outline,
|
|
);
|
|
}
|
|
|
|
/// 创建深色主题颜色方案
|
|
static ColorScheme get darkColorScheme {
|
|
return const ColorScheme.dark(
|
|
primary: primary,
|
|
onPrimary: onPrimary,
|
|
secondary: secondary,
|
|
onSecondary: onSecondary,
|
|
error: error,
|
|
onError: onError,
|
|
background: Color(0xFF121212),
|
|
onBackground: Color(0xFFFFFFFF),
|
|
surface: Color(0xFF1E1E1E),
|
|
onSurface: Color(0xFFFFFFFF),
|
|
surfaceVariant: Color(0xFF2C2C2C),
|
|
onSurfaceVariant: Color(0xFFBDBDBD),
|
|
outline: Color(0xFF424242),
|
|
);
|
|
}
|
|
} |