Files
ShowenV2/clients/flutter/lib/theme/app_theme.dart
showen 8ed9cb2d9d feat: Flutter APK 编译成功 + Gradle 配置修复 + APK 下载部署 + 待优化清单
- 通过 qemu-user-static 实现 ARM64 主机编译 Android APK (51MB)
- 修复 Gradle: Aliyun 镜像 + PREFER_SETTINGS + JVM 内存 1536M
- 部署 APK 到 configs/downloads/, Web 下载接口已验证 (HTTP 200)
- 新增 Flutter TODO.md: 10项待优化 (P0/P1/P2 分级)
- 新增 pm_soul.md, 更新 routes.rs APK 下载路由

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 06:43:55 +08:00

193 lines
6.1 KiB
Dart

import 'package:flutter/material.dart';
import 'app_colors.dart';
class AppTheme {
static ThemeData dark() {
const colorScheme = ColorScheme.dark(
primary: AppColors.primary,
secondary: AppColors.secondary,
surface: AppColors.card,
error: AppColors.error,
onPrimary: Colors.white,
onSecondary: Colors.white,
onSurface: AppColors.textPrimary,
onError: Colors.white,
);
final base = ThemeData(
useMaterial3: true,
brightness: Brightness.dark,
colorScheme: colorScheme,
scaffoldBackgroundColor: AppColors.background,
canvasColor: AppColors.background,
splashColor: AppColors.primary.withValues(alpha: 0.12),
highlightColor: AppColors.primary.withValues(alpha: 0.08),
dividerColor: AppColors.border,
cardColor: AppColors.card,
fontFamily: 'Noto Sans SC',
textTheme: _textTheme,
appBarTheme: const AppBarTheme(
centerTitle: false,
elevation: 0,
backgroundColor: AppColors.background,
foregroundColor: AppColors.textPrimary,
titleTextStyle: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w600,
color: AppColors.textPrimary,
fontFamily: 'Noto Sans SC',
fontFamilyFallback: ['Inter'],
),
),
cardTheme: CardThemeData(
color: AppColors.card,
elevation: 6,
shadowColor: Colors.black.withValues(alpha: 0.20),
margin: EdgeInsets.zero,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(AppRadius.large),
side: const BorderSide(color: AppColors.border),
),
),
inputDecorationTheme: InputDecorationTheme(
filled: true,
fillColor: AppColors.background,
contentPadding: const EdgeInsets.symmetric(
horizontal: 12,
vertical: 12,
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(AppRadius.medium),
borderSide: const BorderSide(color: AppColors.border),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(AppRadius.medium),
borderSide: const BorderSide(color: AppColors.primary),
),
hintStyle: const TextStyle(color: AppColors.textSecondary),
),
navigationBarTheme: NavigationBarThemeData(
backgroundColor: AppColors.card,
height: 64,
indicatorColor: AppColors.primary.withValues(alpha: 0.18),
labelTextStyle: WidgetStateProperty.all(
const TextStyle(
fontSize: 12,
fontWeight: FontWeight.w500,
fontFamily: 'Inter',
fontFamilyFallback: ['Noto Sans SC'],
),
),
iconTheme: WidgetStateProperty.resolveWith(
(states) => IconThemeData(
size: 24,
color: states.contains(WidgetState.selected)
? AppColors.textPrimary
: AppColors.textSecondary,
),
),
),
filledButtonTheme: FilledButtonThemeData(
style: FilledButton.styleFrom(
minimumSize: const Size.fromHeight(48),
backgroundColor: AppColors.primary,
foregroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(AppRadius.medium),
),
textStyle: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
fontFamily: 'Inter',
fontFamilyFallback: ['Noto Sans SC'],
),
),
),
outlinedButtonTheme: OutlinedButtonThemeData(
style: OutlinedButton.styleFrom(
minimumSize: const Size.fromHeight(48),
foregroundColor: AppColors.primary,
side: const BorderSide(color: AppColors.primary),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(AppRadius.medium),
),
),
),
switchTheme: SwitchThemeData(
trackOutlineColor: WidgetStateProperty.all(Colors.transparent),
thumbColor: WidgetStateProperty.resolveWith(
(states) => states.contains(WidgetState.selected)
? AppColors.primary
: AppColors.textSecondary,
),
trackColor: WidgetStateProperty.resolveWith(
(states) => states.contains(WidgetState.selected)
? AppColors.primary.withValues(alpha: 0.4)
: AppColors.border,
),
),
sliderTheme: const SliderThemeData(
activeTrackColor: AppColors.primary,
inactiveTrackColor: AppColors.border,
thumbColor: AppColors.primary,
trackHeight: 4,
thumbShape: RoundSliderThumbShape(enabledThumbRadius: 10),
),
);
return base.copyWith(
textSelectionTheme: const TextSelectionThemeData(
cursorColor: AppColors.primary,
selectionColor: Color(0x446366F1),
selectionHandleColor: AppColors.primary,
),
);
}
static const TextTheme _textTheme = TextTheme(
headlineLarge: TextStyle(
fontSize: 32,
fontWeight: FontWeight.w700,
color: AppColors.textPrimary,
fontFamily: 'Inter',
fontFamilyFallback: ['Noto Sans SC'],
),
headlineMedium: TextStyle(
fontSize: 24,
fontWeight: FontWeight.w700,
color: AppColors.textPrimary,
fontFamily: 'Inter',
fontFamilyFallback: ['Noto Sans SC'],
),
headlineSmall: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w600,
color: AppColors.textPrimary,
fontFamily: 'Inter',
fontFamilyFallback: ['Noto Sans SC'],
),
bodyLarge: TextStyle(
fontSize: 16,
height: 1.5,
color: AppColors.textPrimary,
fontFamily: 'Noto Sans SC',
fontFamilyFallback: ['Inter'],
),
bodyMedium: TextStyle(
fontSize: 14,
height: 1.4,
color: AppColors.textSecondary,
fontFamily: 'Noto Sans SC',
fontFamilyFallback: ['Inter'],
),
bodySmall: TextStyle(
fontSize: 12,
height: 1.3,
color: AppColors.textSecondary,
fontFamily: 'Noto Sans SC',
fontFamilyFallback: ['Inter'],
),
);
}