Template
Core 基础设施:Flavor 三包体系、Drift+SQLCipher 加密数据库 7 拦截器 Dio 网络栈、CrashReporter 崩溃日志、Sealed Failure 错误体系 5 色板主题系统、Auth 认证骨架(Clean Architecture)、Dev Panel、Mock Adapter 通过验证:flutter analyze(0 errors)、flutter test(全绿)、staging APK 74.8MB
120 lines
4.5 KiB
Dart
120 lines
4.5 KiB
Dart
import 'package:flutter/material.dart';
|
||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||
|
||
import 'package:sunny_mochi/core/theme/app_colors.dart';
|
||
|
||
/// 应用主题工厂 — 按 [AppColorScheme] 真实切换全部色(对齐 iOS 4 套 plist)。
|
||
///
|
||
/// 与旧版差异:
|
||
/// - 旧版只把 primary 当作 seed,nav/btn/bg 都写死,导致 4 套主题视觉差异不明显
|
||
/// - 新版从 [AppPalettes] 读完整 10 色,AppBar/ColorScheme/extensions 全部按主题切
|
||
/// - 通过 ThemeExtension 暴露 [AppPalette],业务代码 `Theme.of(context).extension<AppPalette>()!.buttonBg` 读
|
||
abstract class AppTheme {
|
||
static ThemeData light({AppColorScheme scheme = AppColorScheme.white}) {
|
||
final palette = AppPalettes.of(scheme);
|
||
return ThemeData(
|
||
useMaterial3: true,
|
||
// BackButton 图标:iOS 平台渲染 arrow_back_ios_new(< 样式),与登录页一致。
|
||
// ScrollBehavior 使用 defaultTargetPlatform,不受此字段影响。
|
||
platform: TargetPlatform.iOS,
|
||
// 全局字体 — HarmonyOS Sans SC(GB2312 子集,pubspec 注册)
|
||
fontFamily: 'HarmonyOS Sans SC',
|
||
colorScheme: ColorScheme.fromSeed(
|
||
seedColor: palette.primary,
|
||
primary: palette.primary,
|
||
secondary: palette.secondary,
|
||
surface: AppColors.surface,
|
||
error: AppColors.error,
|
||
),
|
||
scaffoldBackgroundColor: palette.background,
|
||
primaryColor: palette.primary,
|
||
appBarTheme: AppBarTheme(
|
||
backgroundColor: palette.navBar,
|
||
foregroundColor: palette.navBarText,
|
||
elevation: 0,
|
||
// Material 3 默认会在滚动时给 AppBar 叠加 surfaceTint 染色(紫色);
|
||
// 设计稿要求 navBar 保持纯白,必须显式置为 transparent + 0 elevation。
|
||
surfaceTintColor: Colors.transparent,
|
||
scrolledUnderElevation: 0,
|
||
centerTitle: true,
|
||
titleTextStyle: TextStyle(
|
||
color: palette.navBarText,
|
||
fontSize: 18.sp,
|
||
fontWeight: FontWeight.w600,
|
||
),
|
||
iconTheme: IconThemeData(color: palette.navBarText, size: 22.sp),
|
||
),
|
||
elevatedButtonTheme: ElevatedButtonThemeData(
|
||
style: ElevatedButton.styleFrom(
|
||
backgroundColor: palette.buttonBg,
|
||
foregroundColor: palette.buttonText,
|
||
),
|
||
),
|
||
filledButtonTheme: FilledButtonThemeData(
|
||
style: FilledButton.styleFrom(
|
||
backgroundColor: palette.buttonBg,
|
||
foregroundColor: palette.buttonText,
|
||
),
|
||
),
|
||
textButtonTheme: TextButtonThemeData(
|
||
style: TextButton.styleFrom(foregroundColor: palette.primary),
|
||
),
|
||
tabBarTheme: TabBarThemeData(
|
||
labelColor: palette.tabBarSelected,
|
||
unselectedLabelColor: palette.tabBarNormal,
|
||
indicatorColor: palette.tabBarSelected,
|
||
),
|
||
bottomNavigationBarTheme: BottomNavigationBarThemeData(
|
||
selectedItemColor: palette.tabBarSelected,
|
||
unselectedItemColor: palette.tabBarNormal,
|
||
),
|
||
textTheme: TextTheme(
|
||
bodyLarge: TextStyle(fontSize: 16.sp, color: palette.text),
|
||
bodyMedium: TextStyle(fontSize: 14.sp, color: AppColors.textSecondary),
|
||
bodySmall: TextStyle(fontSize: 12.sp, color: AppColors.textHint),
|
||
titleLarge: TextStyle(
|
||
fontSize: 18.sp,
|
||
fontWeight: FontWeight.w600,
|
||
color: palette.text,
|
||
),
|
||
),
|
||
dividerColor: AppColors.divider,
|
||
dividerTheme: const DividerThemeData(space: 1, thickness: 1),
|
||
extensions: [palette],
|
||
);
|
||
}
|
||
|
||
static ThemeData dark({AppColorScheme scheme = AppColorScheme.white}) {
|
||
final palette = AppPalettes.of(scheme);
|
||
return ThemeData(
|
||
useMaterial3: true,
|
||
platform: TargetPlatform.iOS,
|
||
brightness: Brightness.dark,
|
||
colorScheme: ColorScheme.fromSeed(
|
||
seedColor: palette.primary,
|
||
primary: palette.primary,
|
||
secondary: palette.secondary,
|
||
brightness: Brightness.dark,
|
||
),
|
||
primaryColor: palette.primary,
|
||
scaffoldBackgroundColor: const Color(0xFF121212),
|
||
appBarTheme: AppBarTheme(
|
||
backgroundColor: AppColors.navBarDark,
|
||
foregroundColor: Colors.white,
|
||
elevation: 0,
|
||
centerTitle: true,
|
||
titleTextStyle: TextStyle(
|
||
color: Colors.white,
|
||
fontSize: 17.sp,
|
||
fontWeight: FontWeight.w600,
|
||
),
|
||
),
|
||
bottomNavigationBarTheme: BottomNavigationBarThemeData(
|
||
selectedItemColor: palette.tabBarSelected,
|
||
unselectedItemColor: palette.tabBarNormal,
|
||
),
|
||
extensions: [palette],
|
||
);
|
||
}
|
||
}
|