156 lines
5.4 KiB
Dart
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;
|
|
}
|
|
}
|