refactor(theme): 迁移主题感知颜色至 ThemeExtension
- 创建 AppThemeColors ThemeExtension 类,统一管理主题感知颜色(涨跌色、卡片背景、渐变等) - 从 AppColorScheme 移除主题感知辅助函数,仅保留静态颜色常量 - 在 AppTheme 中注册 ThemeExtension,支持深色/浅色主题工厂 - 重构所有 UI 组件使用 context.appColors 访问主题颜色,替代硬编码的 AppColorScheme 方法调用 - 移除组件中重复的 isDark 判断逻辑,简化颜色获取方式 - 保持向后兼容性,所有现有功能不变
This commit is contained in:
@@ -178,57 +178,14 @@ class AppColorScheme {
|
||||
static const Color info = Color(0xFF2196F3);
|
||||
|
||||
// ============================================
|
||||
// 主题感知辅助函数 - 根据明暗模式选择正确的颜色
|
||||
// 主题感知辅助函数 - 已迁移至 AppThemeColors ThemeExtension
|
||||
// 以下方法保留仅供 AppThemeColors 工厂内部使用
|
||||
// ============================================
|
||||
|
||||
/// 获取涨跌颜色(主题感知)
|
||||
///
|
||||
/// 在深色模式下使用亮绿色 (#afffd1),在亮色模式下使用深绿色 (#00a878) 以确保对比度
|
||||
static Color getUpColor(bool isDark) => isDark ? darkTertiary : lightTertiary;
|
||||
|
||||
/// 获取涨跌背景色(主题感知)
|
||||
///
|
||||
/// 带透明度的背景色,用于标签、徽章等
|
||||
static Color getUpBackgroundColor(bool isDark, {double opacity = 0.15}) {
|
||||
return isDark
|
||||
? darkTertiary.withValues(alpha: opacity)
|
||||
: lightTertiary.withValues(alpha: opacity);
|
||||
}
|
||||
|
||||
/// 获取跌/卖出颜色(主题感知)
|
||||
static Color getDownColor(bool isDark) => isDark ? darkError : lightError;
|
||||
|
||||
/// 获取跌/卖出背景色(主题感知)
|
||||
static Color getDownBackgroundColor(bool isDark, {double opacity = 0.15}) {
|
||||
return isDark
|
||||
? darkError.withValues(alpha: opacity)
|
||||
: lightError.withValues(alpha: opacity);
|
||||
}
|
||||
|
||||
/// 交易按钮买入色 - 深绿色填充,确保白色文字可读
|
||||
static const Color buyButtonFill = Color(0xFF059669);
|
||||
|
||||
/// 交易按钮卖出色 - 深红色填充,确保白色文字可读
|
||||
static const Color sellButtonFill = Color(0xFFDC2626);
|
||||
|
||||
/// 获取买入按钮渐变(主题感知)
|
||||
static LinearGradient getBuyGradient(bool isDark) => LinearGradient(
|
||||
colors: isDark
|
||||
? [darkTertiary, darkTertiaryContainer]
|
||||
: [lightTertiary, lightTertiaryContainer],
|
||||
begin: const Alignment(-0.7, -0.7),
|
||||
end: const Alignment(0.7, 0.7),
|
||||
);
|
||||
|
||||
/// 获取翡翠渐变(主题感知)- 用于盈利展示
|
||||
static LinearGradient getEmeraldGradient(bool isDark) => LinearGradient(
|
||||
colors: isDark
|
||||
? [darkTertiary, const Color(0xFF7de8b8)]
|
||||
: [lightTertiary, const Color(0xFF00c987)],
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
);
|
||||
|
||||
// ============================================
|
||||
// 渐变预设
|
||||
// ============================================
|
||||
@@ -426,14 +383,6 @@ class AppColorScheme {
|
||||
|
||||
/// 获取买入按钮渐变(主题感知)- 用于盈利展示
|
||||
|
||||
/// 获取涨跌颜色(明暗通用)
|
||||
static Color getChangeColor(bool isUp) => isUp ? AppColorScheme.up : AppColorScheme.down;
|
||||
|
||||
/// 获取涨跌背景色(带透明度)
|
||||
static Color getChangeBackgroundColor(bool isUp, {double opacity = 0.15}) {
|
||||
return isUp
|
||||
? AppColorScheme.up.withValues(alpha: opacity)
|
||||
: AppColorScheme.down.withValues(alpha: opacity);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'app_color_scheme.dart';
|
||||
import 'app_spacing.dart';
|
||||
import 'app_theme_extension.dart';
|
||||
|
||||
/// "The Kinetic Vault" & "The Ethereal Terminal" 主题配置
|
||||
class AppTheme {
|
||||
@@ -18,6 +19,9 @@ class AppTheme {
|
||||
scaffoldBackgroundColor: AppColorScheme.darkBackground,
|
||||
primaryColor: AppColorScheme.darkPrimary,
|
||||
colorScheme: AppColorScheme.darkMaterial,
|
||||
extensions: <ThemeExtension<dynamic>>[
|
||||
AppThemeColors.dark(),
|
||||
],
|
||||
|
||||
// AppBar - 无边框规则
|
||||
appBarTheme: AppBarTheme(
|
||||
@@ -121,6 +125,9 @@ class AppTheme {
|
||||
scaffoldBackgroundColor: AppColorScheme.lightBackground,
|
||||
primaryColor: AppColorScheme.lightPrimary,
|
||||
colorScheme: AppColorScheme.lightMaterial,
|
||||
extensions: <ThemeExtension<dynamic>>[
|
||||
AppThemeColors.light(),
|
||||
],
|
||||
|
||||
// AppBar - 珍珠白
|
||||
appBarTheme: AppBarTheme(
|
||||
|
||||
220
flutter_monisuo/lib/core/theme/app_theme_extension.dart
Normal file
220
flutter_monisuo/lib/core/theme/app_theme_extension.dart
Normal file
@@ -0,0 +1,220 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'app_color_scheme.dart';
|
||||
|
||||
/// 自定义主题扩展 — 注册到 ThemeData.extensions 中
|
||||
///
|
||||
/// 存放 ColorScheme 标准槽位无法覆盖的语义色:
|
||||
/// - 卡片背景语义色(dark/light 使用不同 surface 层级)
|
||||
/// - 涨跌金融色(含带透明度的背景色)
|
||||
/// - 渐变预设
|
||||
/// - 光效透明度等
|
||||
@immutable
|
||||
class AppThemeColors extends ThemeExtension<AppThemeColors> {
|
||||
// ---- 卡片背景语义色 ----
|
||||
/// 标准卡片背景(dark: surfaceContainer, light: surfaceContainerHigh)
|
||||
final Color surfaceCard;
|
||||
|
||||
/// 高亮卡片背景(dark: surfaceContainerHighest, light: surfaceContainerHigh)
|
||||
final Color surfaceCardHigh;
|
||||
|
||||
// ---- 文字语义 ----
|
||||
/// 弱化/辅助文字
|
||||
final Color onSurfaceMuted;
|
||||
|
||||
// ---- 涨跌金融色 ----
|
||||
/// 涨/盈利/买入
|
||||
final Color up;
|
||||
final Color upBackground;
|
||||
|
||||
/// 跌/亏损/卖出
|
||||
final Color down;
|
||||
final Color downBackground;
|
||||
|
||||
// ---- 强调色 ----
|
||||
/// 主强调色(dark: secondary 金色, light: primary 蓝色)
|
||||
final Color accentPrimary;
|
||||
|
||||
// ---- 光效 ----
|
||||
/// 光晕透明度(dark: 0.15, light: 0.08)
|
||||
final double glowOpacity;
|
||||
|
||||
// ---- 边框 ----
|
||||
/// Ghost Border(outlineVariant 带透明度)
|
||||
final Color ghostBorder;
|
||||
|
||||
// ---- 渐变预设 ----
|
||||
final LinearGradient ctaGradient;
|
||||
final LinearGradient buyGradient;
|
||||
final LinearGradient sellGradient;
|
||||
final LinearGradient assetGradient;
|
||||
final LinearGradient emeraldGradient;
|
||||
|
||||
const AppThemeColors({
|
||||
required this.surfaceCard,
|
||||
required this.surfaceCardHigh,
|
||||
required this.onSurfaceMuted,
|
||||
required this.up,
|
||||
required this.upBackground,
|
||||
required this.down,
|
||||
required this.downBackground,
|
||||
required this.accentPrimary,
|
||||
required this.glowOpacity,
|
||||
required this.ghostBorder,
|
||||
required this.ctaGradient,
|
||||
required this.buyGradient,
|
||||
required this.sellGradient,
|
||||
required this.assetGradient,
|
||||
required this.emeraldGradient,
|
||||
});
|
||||
|
||||
/// 深色主题工厂
|
||||
factory AppThemeColors.dark() => AppThemeColors(
|
||||
surfaceCard: AppColorScheme.darkSurfaceContainer,
|
||||
surfaceCardHigh: AppColorScheme.darkSurfaceContainerHighest,
|
||||
onSurfaceMuted: AppColorScheme.darkOnSurfaceMuted,
|
||||
up: AppColorScheme.darkTertiary,
|
||||
upBackground: AppColorScheme.darkTertiary.withValues(alpha: 0.15),
|
||||
down: AppColorScheme.darkError,
|
||||
downBackground: AppColorScheme.darkError.withValues(alpha: 0.15),
|
||||
accentPrimary: AppColorScheme.darkSecondary,
|
||||
glowOpacity: 0.15,
|
||||
ghostBorder: AppColorScheme.darkOutlineVariant.withValues(alpha: 0.15),
|
||||
ctaGradient: AppColorScheme.darkCtaGradient,
|
||||
buyGradient: AppColorScheme.buyGradient,
|
||||
sellGradient: AppColorScheme.sellGradient,
|
||||
assetGradient: AppColorScheme.assetCardGradient,
|
||||
emeraldGradient: const LinearGradient(
|
||||
colors: [AppColorScheme.darkTertiary, Color(0xFF7de8b8)],
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
),
|
||||
);
|
||||
|
||||
/// 浅色主题工厂
|
||||
factory AppThemeColors.light() => AppThemeColors(
|
||||
surfaceCard: AppColorScheme.lightSurfaceContainerHigh,
|
||||
surfaceCardHigh: AppColorScheme.lightSurfaceContainerHigh,
|
||||
onSurfaceMuted: AppColorScheme.lightOnSurfaceMuted,
|
||||
up: AppColorScheme.lightTertiary,
|
||||
upBackground: AppColorScheme.lightTertiary.withValues(alpha: 0.15),
|
||||
down: AppColorScheme.lightError,
|
||||
downBackground: AppColorScheme.lightError.withValues(alpha: 0.15),
|
||||
accentPrimary: AppColorScheme.lightPrimary,
|
||||
glowOpacity: 0.08,
|
||||
ghostBorder: AppColorScheme.lightOutlineVariant.withValues(alpha: 0.5),
|
||||
ctaGradient: AppColorScheme.lightCtaGradient,
|
||||
buyGradient: const LinearGradient(
|
||||
colors: [AppColorScheme.lightTertiary, AppColorScheme.lightTertiaryContainer],
|
||||
begin: Alignment(-0.7, -0.7),
|
||||
end: Alignment(0.7, 0.7),
|
||||
),
|
||||
sellGradient: AppColorScheme.sellGradient,
|
||||
assetGradient: const LinearGradient(
|
||||
colors: [AppColorScheme.lightPrimary, AppColorScheme.lightSecondary],
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
),
|
||||
emeraldGradient: const LinearGradient(
|
||||
colors: [AppColorScheme.lightTertiary, Color(0xFF00c987)],
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
),
|
||||
);
|
||||
|
||||
@override
|
||||
AppThemeColors copyWith({
|
||||
Color? surfaceCard,
|
||||
Color? surfaceCardHigh,
|
||||
Color? onSurfaceMuted,
|
||||
Color? up,
|
||||
Color? upBackground,
|
||||
Color? down,
|
||||
Color? downBackground,
|
||||
Color? accentPrimary,
|
||||
double? glowOpacity,
|
||||
Color? ghostBorder,
|
||||
LinearGradient? ctaGradient,
|
||||
LinearGradient? buyGradient,
|
||||
LinearGradient? sellGradient,
|
||||
LinearGradient? assetGradient,
|
||||
LinearGradient? emeraldGradient,
|
||||
}) {
|
||||
return AppThemeColors(
|
||||
surfaceCard: surfaceCard ?? this.surfaceCard,
|
||||
surfaceCardHigh: surfaceCardHigh ?? this.surfaceCardHigh,
|
||||
onSurfaceMuted: onSurfaceMuted ?? this.onSurfaceMuted,
|
||||
up: up ?? this.up,
|
||||
upBackground: upBackground ?? this.upBackground,
|
||||
down: down ?? this.down,
|
||||
downBackground: downBackground ?? this.downBackground,
|
||||
accentPrimary: accentPrimary ?? this.accentPrimary,
|
||||
glowOpacity: glowOpacity ?? this.glowOpacity,
|
||||
ghostBorder: ghostBorder ?? this.ghostBorder,
|
||||
ctaGradient: ctaGradient ?? this.ctaGradient,
|
||||
buyGradient: buyGradient ?? this.buyGradient,
|
||||
sellGradient: sellGradient ?? this.sellGradient,
|
||||
assetGradient: assetGradient ?? this.assetGradient,
|
||||
emeraldGradient: emeraldGradient ?? this.emeraldGradient,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
AppThemeColors lerp(AppThemeColors other, double t) {
|
||||
if (t < 0.5) {
|
||||
return copyWith(
|
||||
surfaceCard: Color.lerp(surfaceCard, other.surfaceCard, t * 2),
|
||||
surfaceCardHigh:
|
||||
Color.lerp(surfaceCardHigh, other.surfaceCardHigh, t * 2),
|
||||
onSurfaceMuted:
|
||||
Color.lerp(onSurfaceMuted, other.onSurfaceMuted, t * 2),
|
||||
up: Color.lerp(up, other.up, t * 2),
|
||||
upBackground: Color.lerp(upBackground, other.upBackground, t * 2),
|
||||
down: Color.lerp(down, other.down, t * 2),
|
||||
downBackground: Color.lerp(downBackground, other.downBackground, t * 2),
|
||||
accentPrimary:
|
||||
Color.lerp(accentPrimary, other.accentPrimary, t * 2),
|
||||
ghostBorder: Color.lerp(ghostBorder, other.ghostBorder, t * 2),
|
||||
glowOpacity: lerpDouble(glowOpacity, other.glowOpacity, t * 2),
|
||||
);
|
||||
}
|
||||
return other.copyWith(
|
||||
surfaceCard: Color.lerp(other.surfaceCard, surfaceCard, (1 - t) * 2),
|
||||
surfaceCardHigh: Color.lerp(
|
||||
other.surfaceCardHigh, surfaceCardHigh, (1 - t) * 2),
|
||||
onSurfaceMuted:
|
||||
Color.lerp(other.onSurfaceMuted, onSurfaceMuted, (1 - t) * 2),
|
||||
up: Color.lerp(other.up, up, (1 - t) * 2),
|
||||
upBackground: Color.lerp(other.upBackground, upBackground, (1 - t) * 2),
|
||||
down: Color.lerp(other.down, down, (1 - t) * 2),
|
||||
downBackground:
|
||||
Color.lerp(other.downBackground, downBackground, (1 - t) * 2),
|
||||
accentPrimary:
|
||||
Color.lerp(other.accentPrimary, accentPrimary, (1 - t) * 2),
|
||||
ghostBorder: Color.lerp(other.ghostBorder, ghostBorder, (1 - t) * 2),
|
||||
glowOpacity: lerpDouble(other.glowOpacity, glowOpacity, (1 - t) * 2),
|
||||
);
|
||||
}
|
||||
|
||||
static double lerpDouble(double a, double b, double t) => a + (b - a) * t;
|
||||
}
|
||||
|
||||
/// BuildContext 主题快捷扩展
|
||||
///
|
||||
/// 用法:
|
||||
/// context.colors.primary → Theme.of(context).colorScheme.primary
|
||||
/// context.appColors.up → AppThemeColors 中的涨色
|
||||
/// context.isDark → 是否深色模式
|
||||
extension AppThemeContext on BuildContext {
|
||||
/// Material ColorScheme 快捷访问
|
||||
ColorScheme get colors => Theme.of(this).colorScheme;
|
||||
|
||||
/// 自定义语义色快捷访问
|
||||
AppThemeColors get appColors =>
|
||||
Theme.of(this).extension<AppThemeColors>()!;
|
||||
|
||||
/// 是否深色模式
|
||||
bool get isDark => Theme.of(this).brightness == Brightness.dark;
|
||||
|
||||
/// TextTheme 快捷访问
|
||||
TextTheme get textStyles => Theme.of(this).textTheme;
|
||||
}
|
||||
Reference in New Issue
Block a user