Files
ReelShort/lib/core/theme/app_theme.dart
T

156 lines
5.4 KiB
Dart

// Author: fruit.com.cn
import 'package:flutter/material.dart';
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,
colors: [AppColors.surfaceTop, AppColors.ink],
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(
primary: AppColors.blue,
onPrimary: AppColors.onPrimary,
secondary: AppColors.secondary,
onSecondary: AppColors.onPrimary,
primaryContainer: AppColors.surfaceTop,
onPrimaryContainer: AppColors.onSurface,
secondaryContainer: AppColors.badgePink,
onSecondaryContainer: AppColors.badgePinkText,
surface: AppColors.ink,
onSurface: AppColors.onSurface,
outline: AppColors.border,
outlineVariant: AppColors.border,
surfaceTint: AppColors.blue,
inversePrimary: AppColors.bluePressed,
);
final base = ThemeData(
useMaterial3: true,
brightness: Brightness.light,
colorScheme: scheme,
scaffoldBackgroundColor: AppColors.ink,
fontFamily: 'PlusJakartaSans',
progressIndicatorTheme: const ProgressIndicatorThemeData(
color: AppColors.blue,
),
sliderTheme: const SliderThemeData(
activeTrackColor: AppColors.blue,
inactiveTrackColor: AppColors.border,
thumbColor: AppColors.onPrimary,
),
tabBarTheme: const TabBarThemeData(
labelColor: AppColors.blue,
indicatorColor: AppColors.blue,
unselectedLabelColor: AppColors.muted,
),
textButtonTheme: TextButtonThemeData(
style: TextButton.styleFrom(foregroundColor: AppColors.blue),
),
filledButtonTheme: FilledButtonThemeData(
style: ButtonStyle(
backgroundColor: WidgetStateProperty.resolveWith(_buttonColor),
foregroundColor: const WidgetStatePropertyAll(AppColors.onPrimary),
minimumSize: const WidgetStatePropertyAll(
Size(0, AppDimens.buttonHeight),
),
shape: const WidgetStatePropertyAll(StadiumBorder()),
),
),
outlinedButtonTheme: OutlinedButtonThemeData(
style: ButtonStyle(
foregroundColor: const WidgetStatePropertyAll(AppColors.blue),
minimumSize: const WidgetStatePropertyAll(
Size(0, AppDimens.buttonHeight),
),
side: const WidgetStatePropertyAll(
BorderSide(color: AppColors.border),
),
shape: const WidgetStatePropertyAll(StadiumBorder()),
),
),
appBarTheme: const AppBarTheme(
backgroundColor: AppColors.ink,
foregroundColor: AppColors.onSurface,
elevation: 0,
systemOverlayStyle: SystemUiOverlayStyle.dark,
titleTextStyle: TextStyle(
color: AppColors.onSurface,
fontFamily: 'Outfit',
fontSize: AppDimens.pageTitle,
fontWeight: FontWeight.w800,
),
),
iconTheme: const IconThemeData(color: AppColors.onSurface),
dividerTheme: const DividerThemeData(color: AppColors.border),
cardTheme: const CardThemeData(
color: AppColors.card,
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(AppDimens.cardRadius)),
side: BorderSide(color: AppColors.border),
),
),
switchTheme: SwitchThemeData(
thumbColor: WidgetStateProperty.resolveWith(
(states) => states.contains(WidgetState.selected)
? AppColors.onPrimary
: null,
),
trackColor: WidgetStateProperty.resolveWith(
(states) =>
states.contains(WidgetState.selected) ? AppColors.blue : null,
),
),
snackBarTheme: const SnackBarThemeData(
backgroundColor: AppColors.onSurface,
contentTextStyle: TextStyle(color: AppColors.onPrimary),
),
);
final textTheme = base.textTheme
.apply(
fontFamily: 'PlusJakartaSans',
bodyColor: AppColors.cream,
displayColor: AppColors.onSurface,
)
.copyWith(
displayLarge: _display(base.textTheme.displayLarge),
displayMedium: _display(base.textTheme.displayMedium),
displaySmall: _display(base.textTheme.displaySmall),
headlineLarge: _display(base.textTheme.headlineLarge),
headlineMedium: _display(base.textTheme.headlineMedium),
headlineSmall: _display(base.textTheme.headlineSmall),
titleLarge: _display(base.textTheme.titleLarge),
);
return base.copyWith(textTheme: textTheme);
}
static TextStyle? _display(TextStyle? style) =>
style?.copyWith(fontFamily: 'Outfit', color: AppColors.onSurface);
static Color _buttonColor(Set<WidgetState> states) {
if (states.contains(WidgetState.pressed) ||
states.contains(WidgetState.hovered) ||
states.contains(WidgetState.focused)) {
return AppColors.bluePressed;
}
return AppColors.blue;
}
}