style(theme): 客户端切换深色视觉风格
This commit is contained in:
1 parent
295c21513c
commit
4bc04fd8ae
75 files changed
+732
-330
No files matched your search
+140
-24
@@ -6,9 +6,9 @@ import 'package:flutter/services.dart';
|
||||
import 'app_colors.dart';
|
||||
import 'app_dimens.dart';
|
||||
|
||||
/// K28-S 浅色暖橙主题。
|
||||
/// 深色视觉主题(默认且唯一)。
|
||||
abstract final class AppTheme {
|
||||
/// 页面顶部暖色到米白背景的渐变。
|
||||
/// 页面背景:深色扁平,靠容器层次区分。
|
||||
static const LinearGradient pageGradient = LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
@@ -16,36 +16,50 @@ abstract final class AppTheme {
|
||||
stops: [0, 0.24],
|
||||
);
|
||||
|
||||
/// 卡片轻阴影。
|
||||
/// 卡片阴影关闭,改用底色与分割线。
|
||||
static const BoxShadow cardShadow = BoxShadow(
|
||||
color: AppColors.cardShadow,
|
||||
blurRadius: AppDimens.cardShadowBlur,
|
||||
offset: Offset(0, AppDimens.cardShadowY),
|
||||
);
|
||||
|
||||
/// 全局浅色暖橙主题。
|
||||
static ThemeData light() {
|
||||
const scheme = ColorScheme.light(
|
||||
static final BorderRadius _buttonRadius = BorderRadius.circular(
|
||||
AppDimens.buttonRadius,
|
||||
);
|
||||
static final BorderRadius _cardRadius = BorderRadius.circular(
|
||||
AppDimens.cardRadius,
|
||||
);
|
||||
static final BorderRadius _inputRadius = BorderRadius.circular(
|
||||
AppDimens.inputRadius,
|
||||
);
|
||||
|
||||
/// 全局深色主题。
|
||||
static ThemeData dark() {
|
||||
const scheme = ColorScheme.dark(
|
||||
primary: AppColors.blue,
|
||||
onPrimary: AppColors.onPrimary,
|
||||
secondary: AppColors.secondary,
|
||||
onSecondary: AppColors.onPrimary,
|
||||
primaryContainer: AppColors.surfaceTop,
|
||||
onSecondary: AppColors.ink,
|
||||
primaryContainer: AppColors.raised,
|
||||
onPrimaryContainer: AppColors.onSurface,
|
||||
secondaryContainer: AppColors.badgePink,
|
||||
onSecondaryContainer: AppColors.badgePinkText,
|
||||
surface: AppColors.ink,
|
||||
onSurface: AppColors.onSurface,
|
||||
surfaceContainerHighest: AppColors.raised,
|
||||
outline: AppColors.border,
|
||||
outlineVariant: AppColors.border,
|
||||
surfaceTint: AppColors.blue,
|
||||
surfaceTint: AppColors.transparent,
|
||||
inversePrimary: AppColors.bluePressed,
|
||||
error: AppColors.error,
|
||||
onError: AppColors.onPrimary,
|
||||
);
|
||||
final base = ThemeData(
|
||||
useMaterial3: true,
|
||||
brightness: Brightness.light,
|
||||
brightness: Brightness.dark,
|
||||
colorScheme: scheme,
|
||||
scaffoldBackgroundColor: AppColors.ink,
|
||||
canvasColor: AppColors.ink,
|
||||
fontFamily: 'PlusJakartaSans',
|
||||
progressIndicatorTheme: const ProgressIndicatorThemeData(
|
||||
color: AppColors.blue,
|
||||
@@ -61,7 +75,23 @@ abstract final class AppTheme {
|
||||
unselectedLabelColor: AppColors.muted,
|
||||
),
|
||||
textButtonTheme: TextButtonThemeData(
|
||||
style: TextButton.styleFrom(foregroundColor: AppColors.blue),
|
||||
style: TextButton.styleFrom(
|
||||
foregroundColor: AppColors.secondary,
|
||||
shape: RoundedRectangleBorder(borderRadius: _buttonRadius),
|
||||
),
|
||||
),
|
||||
elevatedButtonTheme: ElevatedButtonThemeData(
|
||||
style: ButtonStyle(
|
||||
backgroundColor: WidgetStateProperty.resolveWith(_buttonColor),
|
||||
foregroundColor: const WidgetStatePropertyAll(AppColors.onPrimary),
|
||||
elevation: const WidgetStatePropertyAll(0),
|
||||
minimumSize: const WidgetStatePropertyAll(
|
||||
Size(0, AppDimens.buttonHeight),
|
||||
),
|
||||
shape: WidgetStatePropertyAll(
|
||||
RoundedRectangleBorder(borderRadius: _buttonRadius),
|
||||
),
|
||||
),
|
||||
),
|
||||
filledButtonTheme: FilledButtonThemeData(
|
||||
style: ButtonStyle(
|
||||
@@ -70,7 +100,9 @@ abstract final class AppTheme {
|
||||
minimumSize: const WidgetStatePropertyAll(
|
||||
Size(0, AppDimens.buttonHeight),
|
||||
),
|
||||
shape: const WidgetStatePropertyAll(StadiumBorder()),
|
||||
shape: WidgetStatePropertyAll(
|
||||
RoundedRectangleBorder(borderRadius: _buttonRadius),
|
||||
),
|
||||
),
|
||||
),
|
||||
outlinedButtonTheme: OutlinedButtonThemeData(
|
||||
@@ -82,14 +114,46 @@ abstract final class AppTheme {
|
||||
side: const WidgetStatePropertyAll(
|
||||
BorderSide(color: AppColors.border),
|
||||
),
|
||||
shape: const WidgetStatePropertyAll(StadiumBorder()),
|
||||
shape: WidgetStatePropertyAll(
|
||||
RoundedRectangleBorder(borderRadius: _buttonRadius),
|
||||
),
|
||||
),
|
||||
),
|
||||
inputDecorationTheme: InputDecorationTheme(
|
||||
filled: true,
|
||||
fillColor: AppColors.input,
|
||||
hintStyle: const TextStyle(color: AppColors.subtle),
|
||||
labelStyle: const TextStyle(color: AppColors.muted),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: _inputRadius,
|
||||
borderSide: const BorderSide(color: AppColors.border),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: _inputRadius,
|
||||
borderSide: const BorderSide(color: AppColors.border),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: _inputRadius,
|
||||
borderSide: const BorderSide(color: AppColors.blue),
|
||||
),
|
||||
),
|
||||
chipTheme: ChipThemeData(
|
||||
backgroundColor: AppColors.raised,
|
||||
selectedColor: AppColors.blue.withValues(alpha: 0.22),
|
||||
labelStyle: const TextStyle(color: AppColors.onSurface),
|
||||
secondaryLabelStyle: const TextStyle(color: AppColors.muted),
|
||||
side: const BorderSide(color: AppColors.border),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(AppDimens.chipRadius),
|
||||
),
|
||||
),
|
||||
appBarTheme: const AppBarTheme(
|
||||
backgroundColor: AppColors.ink,
|
||||
backgroundColor: AppColors.card,
|
||||
foregroundColor: AppColors.onSurface,
|
||||
elevation: 0,
|
||||
systemOverlayStyle: SystemUiOverlayStyle.dark,
|
||||
scrolledUnderElevation: 0,
|
||||
surfaceTintColor: AppColors.transparent,
|
||||
systemOverlayStyle: SystemUiOverlayStyle.light,
|
||||
titleTextStyle: TextStyle(
|
||||
color: AppColors.onSurface,
|
||||
fontFamily: 'Outfit',
|
||||
@@ -98,19 +162,47 @@ abstract final class AppTheme {
|
||||
),
|
||||
),
|
||||
iconTheme: const IconThemeData(color: AppColors.onSurface),
|
||||
dividerTheme: const DividerThemeData(color: AppColors.border),
|
||||
cardTheme: const CardThemeData(
|
||||
dividerTheme: const DividerThemeData(
|
||||
color: AppColors.border,
|
||||
thickness: 1,
|
||||
space: 1,
|
||||
),
|
||||
cardTheme: CardThemeData(
|
||||
color: AppColors.card,
|
||||
elevation: 0,
|
||||
shadowColor: AppColors.transparent,
|
||||
surfaceTintColor: AppColors.transparent,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(AppDimens.cardRadius)),
|
||||
side: BorderSide(color: AppColors.border),
|
||||
borderRadius: _cardRadius,
|
||||
side: const BorderSide(color: AppColors.border),
|
||||
),
|
||||
),
|
||||
dialogTheme: DialogThemeData(
|
||||
backgroundColor: AppColors.raised,
|
||||
surfaceTintColor: AppColors.transparent,
|
||||
shape: RoundedRectangleBorder(borderRadius: _cardRadius),
|
||||
titleTextStyle: const TextStyle(
|
||||
color: AppColors.onSurface,
|
||||
fontFamily: 'Outfit',
|
||||
fontSize: AppDimens.sectionTitle,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
contentTextStyle: const TextStyle(
|
||||
color: AppColors.muted,
|
||||
fontSize: AppDimens.body,
|
||||
),
|
||||
),
|
||||
bottomNavigationBarTheme: const BottomNavigationBarThemeData(
|
||||
backgroundColor: AppColors.bar,
|
||||
selectedItemColor: AppColors.blue,
|
||||
unselectedItemColor: AppColors.navUnselected,
|
||||
elevation: 0,
|
||||
type: BottomNavigationBarType.fixed,
|
||||
),
|
||||
bottomSheetTheme: const BottomSheetThemeData(
|
||||
backgroundColor: Colors.transparent,
|
||||
modalBackgroundColor: Colors.transparent,
|
||||
surfaceTintColor: Colors.transparent,
|
||||
backgroundColor: AppColors.transparent,
|
||||
modalBackgroundColor: AppColors.transparent,
|
||||
surfaceTintColor: AppColors.transparent,
|
||||
),
|
||||
switchTheme: SwitchThemeData(
|
||||
thumbColor: WidgetStateProperty.resolveWith(
|
||||
@@ -124,8 +216,13 @@ abstract final class AppTheme {
|
||||
),
|
||||
),
|
||||
snackBarTheme: const SnackBarThemeData(
|
||||
backgroundColor: AppColors.onSurface,
|
||||
contentTextStyle: TextStyle(color: AppColors.onPrimary),
|
||||
backgroundColor: AppColors.raised,
|
||||
contentTextStyle: TextStyle(color: AppColors.onSurface),
|
||||
actionTextColor: AppColors.secondary,
|
||||
),
|
||||
listTileTheme: const ListTileThemeData(
|
||||
iconColor: AppColors.onSurface,
|
||||
textColor: AppColors.onSurface,
|
||||
),
|
||||
);
|
||||
final textTheme = base.textTheme
|
||||
@@ -142,10 +239,29 @@ abstract final class AppTheme {
|
||||
headlineMedium: _display(base.textTheme.headlineMedium),
|
||||
headlineSmall: _display(base.textTheme.headlineSmall),
|
||||
titleLarge: _display(base.textTheme.titleLarge),
|
||||
bodyLarge: base.textTheme.bodyLarge?.copyWith(
|
||||
color: AppColors.onSurface,
|
||||
),
|
||||
bodyMedium: base.textTheme.bodyMedium?.copyWith(
|
||||
color: AppColors.onSurface,
|
||||
),
|
||||
bodySmall: base.textTheme.bodySmall?.copyWith(color: AppColors.muted),
|
||||
labelLarge: base.textTheme.labelLarge?.copyWith(
|
||||
color: AppColors.onSurface,
|
||||
),
|
||||
labelMedium: base.textTheme.labelMedium?.copyWith(
|
||||
color: AppColors.muted,
|
||||
),
|
||||
labelSmall: base.textTheme.labelSmall?.copyWith(
|
||||
color: AppColors.subtle,
|
||||
),
|
||||
);
|
||||
return base.copyWith(textTheme: textTheme);
|
||||
}
|
||||
|
||||
/// 兼容旧调用点,统一落到深色主题。
|
||||
static ThemeData light() => dark();
|
||||
|
||||
static TextStyle? _display(TextStyle? style) =>
|
||||
style?.copyWith(fontFamily: 'Outfit', color: AppColors.onSurface);
|
||||
|
||||
|
||||
Reference in new issue
Block a user