Files
SkyJourney 61017f1c39 chore: 初始化脚手架 — sunny_mochi 企业级 Flutter 模板
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
2026-05-14 12:51:05 +08:00

120 lines
4.5 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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 当作 seednav/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 SCGB2312 子集,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],
);
}
}