| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379 |
- import 'package:flutter/material.dart';
- import 'package:flutter/services.dart';
- import 'app_colors.dart';
- /// CEX App 主题配置
- ///
- /// 字体:Inter(需在 assets/fonts/ 放置字体文件,pubspec.yaml 已配置)
- /// 数字区域必须叠加 FontFeature.tabularFigures(),见 AppTheme.numericStyle()
- abstract class AppTheme {
- // ── 等宽数字辅助 ─────────────────────────────────────────────
- /// 在行情列表、订单簿、资产金额等数字密集区域,
- /// 将此叠加到 TextStyle 上,防止数值跳动时宽度抖动。
- ///
- /// 用法:style: AppTheme.numericStyle(base)
- static TextStyle numericStyle(TextStyle base) => base.copyWith(
- fontFeatures: const [FontFeature.tabularFigures()],
- );
- // ── 深色主题(默认)──────────────────────────────────────────
- static ThemeData get dark {
- final base = ThemeData.dark(useMaterial3: true);
- return base.copyWith(
- scaffoldBackgroundColor: AppColors.darkBg,
- colorScheme: const ColorScheme.dark(
- primary: AppColors.brand,
- onPrimary: Colors.black,
- secondary: AppColors.brand,
- onSecondary: Colors.black,
- surface: AppColors.darkBgSecondary,
- onSurface: AppColors.darkTextPrimary,
- error: AppColors.error,
- onError: Colors.white,
- outline: AppColors.darkDivider,
- ),
- appBarTheme: const AppBarTheme(
- backgroundColor: AppColors.darkBg,
- foregroundColor: AppColors.darkTextPrimary,
- elevation: 0,
- scrolledUnderElevation: 0,
- systemOverlayStyle: SystemUiOverlayStyle(
- statusBarColor: Colors.transparent,
- statusBarIconBrightness: Brightness.light,
- ),
- titleTextStyle: TextStyle(
- fontFamily: 'Inter',
- color: AppColors.darkTextPrimary,
- fontSize: 16,
- fontWeight: FontWeight.w600,
- ),
- ),
- bottomNavigationBarTheme: const BottomNavigationBarThemeData(
- backgroundColor: AppColors.darkBgSecondary,
- selectedItemColor: AppColors.brand,
- unselectedItemColor: AppColors.darkTextSecondary,
- type: BottomNavigationBarType.fixed,
- elevation: 8,
- ),
- cardTheme: CardThemeData(
- color: AppColors.darkBgSecondary,
- elevation: 0,
- margin: EdgeInsets.zero,
- shape: RoundedRectangleBorder(
- borderRadius: BorderRadius.circular(12),
- side: const BorderSide(color: AppColors.darkCardBorder, width: 0.5),
- ),
- ),
- inputDecorationTheme: InputDecorationTheme(
- filled: true,
- fillColor: AppColors.darkBgTertiary,
- border: OutlineInputBorder(
- borderRadius: BorderRadius.circular(10),
- borderSide: BorderSide.none,
- ),
- enabledBorder: OutlineInputBorder(
- borderRadius: BorderRadius.circular(10),
- borderSide: BorderSide.none,
- ),
- focusedBorder: OutlineInputBorder(
- borderRadius: BorderRadius.circular(10),
- borderSide: const BorderSide(color: AppColors.darkTextPrimary),
- ),
- errorBorder: OutlineInputBorder(
- borderRadius: BorderRadius.circular(10),
- borderSide: const BorderSide(color: AppColors.error),
- ),
- hintStyle: const TextStyle(
- fontFamily: 'Inter',
- color: AppColors.darkTextDisabled,
- ),
- contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
- ),
- elevatedButtonTheme: ElevatedButtonThemeData(
- style: ElevatedButton.styleFrom(
- backgroundColor: AppColors.brand,
- foregroundColor: Colors.black,
- minimumSize: const Size(double.infinity, 48),
- shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
- textStyle: const TextStyle(
- fontFamily: 'Inter',
- fontSize: 16,
- fontWeight: FontWeight.w600,
- ),
- ),
- ),
- textButtonTheme: TextButtonThemeData(
- style: TextButton.styleFrom(foregroundColor: AppColors.brand),
- ),
- dividerTheme: const DividerThemeData(
- color: AppColors.darkDivider,
- thickness: 1,
- space: 1,
- ),
- tabBarTheme: const TabBarThemeData(
- labelColor: AppColors.brand,
- unselectedLabelColor: AppColors.darkTextSecondary,
- indicatorColor: AppColors.brand,
- dividerColor: Colors.transparent,
- labelStyle: TextStyle(
- fontFamily: 'Inter',
- fontSize: 14,
- fontWeight: FontWeight.w600,
- ),
- unselectedLabelStyle: TextStyle(
- fontFamily: 'Inter',
- fontSize: 14,
- fontWeight: FontWeight.w400,
- ),
- ),
- bottomSheetTheme: const BottomSheetThemeData(
- constraints: BoxConstraints(maxWidth: double.infinity),
- ),
- chipTheme: ChipThemeData(
- backgroundColor: AppColors.darkBgTertiary,
- selectedColor: AppColors.brand.withAlpha(30),
- labelStyle: const TextStyle(
- fontFamily: 'Inter',
- color: AppColors.darkTextPrimary,
- fontSize: 12,
- ),
- side: BorderSide.none,
- shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(4)),
- ),
- // ── TextTheme(对应规范 2.6 节)──────────────────────────
- // xs=10 sm=12 base=14 lg=16 xl=18 2xl=20 3xl=24 4xl=28 5xl=32
- textTheme: const TextTheme(
- // 页面主标题:18px w700
- titleLarge: TextStyle(
- fontFamily: 'Inter',
- color: AppColors.darkTextPrimary,
- fontSize: 18,
- fontWeight: FontWeight.w700,
- ),
- // 区域标题 / AppBar:16px w600
- titleMedium: TextStyle(
- fontFamily: 'Inter',
- color: AppColors.darkTextPrimary,
- fontSize: 16,
- fontWeight: FontWeight.w600,
- ),
- // 次级标题:14px w600
- titleSmall: TextStyle(
- fontFamily: 'Inter',
- color: AppColors.darkTextPrimary,
- fontSize: 14,
- fontWeight: FontWeight.w600,
- ),
- // 正文主要:14px w400
- bodyLarge: TextStyle(
- fontFamily: 'Inter',
- color: AppColors.darkTextPrimary,
- fontSize: 14,
- fontWeight: FontWeight.w400,
- ),
- // 正文次要:12px w400
- bodyMedium: TextStyle(
- fontFamily: 'Inter',
- color: AppColors.darkTextPrimary,
- fontSize: 12,
- fontWeight: FontWeight.w400,
- ),
- // 辅助说明:10px w400
- bodySmall: TextStyle(
- fontFamily: 'Inter',
- color: AppColors.darkTextSecondary,
- fontSize: 10,
- fontWeight: FontWeight.w400,
- ),
- // 按钮文字:16px w600
- labelLarge: TextStyle(
- fontFamily: 'Inter',
- color: AppColors.darkTextPrimary,
- fontSize: 16,
- fontWeight: FontWeight.w600,
- ),
- labelMedium: TextStyle(
- fontFamily: 'Inter',
- color: AppColors.darkTextSecondary,
- fontSize: 12,
- fontWeight: FontWeight.w400,
- ),
- // 禁用文字 / 角标:12px w400
- labelSmall: TextStyle(
- fontFamily: 'Inter',
- color: AppColors.darkTextDisabled,
- fontSize: 12,
- fontWeight: FontWeight.w400,
- ),
- ),
- );
- }
- // ── 浅色主题 ──────────────────────────────────────────────────
- static ThemeData get light {
- final base = ThemeData.light(useMaterial3: true);
- return base.copyWith(
- scaffoldBackgroundColor: AppColors.lightBg,
- colorScheme: const ColorScheme.light(
- primary: AppColors.brand,
- onPrimary: Colors.black,
- secondary: AppColors.brand,
- onSecondary: Colors.black,
- surface: AppColors.lightBgSecondary,
- onSurface: AppColors.lightTextPrimary,
- error: AppColors.error,
- onError: Colors.white,
- outline: AppColors.lightDivider,
- ),
- appBarTheme: const AppBarTheme(
- backgroundColor: AppColors.lightBg,
- foregroundColor: AppColors.lightTextPrimary,
- elevation: 0,
- scrolledUnderElevation: 0,
- systemOverlayStyle: SystemUiOverlayStyle(
- statusBarColor: Colors.transparent,
- statusBarIconBrightness: Brightness.dark,
- ),
- titleTextStyle: TextStyle(
- fontFamily: 'Inter',
- color: AppColors.lightTextPrimary,
- fontSize: 16,
- fontWeight: FontWeight.w600,
- ),
- ),
- bottomNavigationBarTheme: const BottomNavigationBarThemeData(
- backgroundColor: AppColors.lightBg,
- selectedItemColor: AppColors.brand,
- unselectedItemColor: AppColors.lightTextSecondary,
- type: BottomNavigationBarType.fixed,
- elevation: 8,
- ),
- cardTheme: const CardThemeData(
- color: AppColors.lightBgSecondary,
- elevation: 0,
- margin: EdgeInsets.zero,
- ),
- inputDecorationTheme: InputDecorationTheme(
- filled: true,
- fillColor: AppColors.lightBgTertiary,
- border: OutlineInputBorder(
- borderRadius: BorderRadius.circular(10),
- borderSide: BorderSide.none,
- ),
- enabledBorder: OutlineInputBorder(
- borderRadius: BorderRadius.circular(10),
- borderSide: BorderSide.none,
- ),
- focusedBorder: OutlineInputBorder(
- borderRadius: BorderRadius.circular(10),
- borderSide: const BorderSide(color: AppColors.lightTextPrimary),
- ),
- errorBorder: OutlineInputBorder(
- borderRadius: BorderRadius.circular(10),
- borderSide: const BorderSide(color: AppColors.error),
- ),
- hintStyle: const TextStyle(
- fontFamily: 'Inter',
- color: AppColors.lightTextDisabled,
- ),
- contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
- ),
- elevatedButtonTheme: ElevatedButtonThemeData(
- style: ElevatedButton.styleFrom(
- backgroundColor: AppColors.brand,
- foregroundColor: Colors.black,
- minimumSize: const Size(double.infinity, 48),
- shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
- textStyle: const TextStyle(
- fontFamily: 'Inter',
- fontSize: 16,
- fontWeight: FontWeight.w600,
- ),
- ),
- ),
- textButtonTheme: TextButtonThemeData(
- style: TextButton.styleFrom(foregroundColor: AppColors.brand),
- ),
- dividerTheme: const DividerThemeData(
- color: AppColors.lightDivider,
- thickness: 1,
- space: 1,
- ),
- tabBarTheme: const TabBarThemeData(
- labelColor: AppColors.brand,
- unselectedLabelColor: AppColors.lightTextSecondary,
- indicatorColor: AppColors.brand,
- dividerColor: Colors.transparent,
- labelStyle: TextStyle(
- fontFamily: 'Inter',
- fontSize: 14,
- fontWeight: FontWeight.w600,
- ),
- unselectedLabelStyle: TextStyle(
- fontFamily: 'Inter',
- fontSize: 14,
- fontWeight: FontWeight.w400,
- ),
- ),
- bottomSheetTheme: const BottomSheetThemeData(
- constraints: BoxConstraints(maxWidth: double.infinity),
- ),
- textTheme: const TextTheme(
- titleLarge: TextStyle(
- fontFamily: 'Inter',
- color: AppColors.lightTextPrimary,
- fontSize: 18,
- fontWeight: FontWeight.w700,
- ),
- titleMedium: TextStyle(
- fontFamily: 'Inter',
- color: AppColors.lightTextPrimary,
- fontSize: 16,
- fontWeight: FontWeight.w600,
- ),
- titleSmall: TextStyle(
- fontFamily: 'Inter',
- color: AppColors.lightTextPrimary,
- fontSize: 14,
- fontWeight: FontWeight.w600,
- ),
- bodyLarge: TextStyle(
- fontFamily: 'Inter',
- color: AppColors.lightTextPrimary,
- fontSize: 14,
- fontWeight: FontWeight.w400,
- ),
- bodyMedium: TextStyle(
- fontFamily: 'Inter',
- color: AppColors.lightTextPrimary,
- fontSize: 12,
- fontWeight: FontWeight.w400,
- ),
- bodySmall: TextStyle(
- fontFamily: 'Inter',
- color: AppColors.lightTextSecondary,
- fontSize: 10,
- fontWeight: FontWeight.w400,
- ),
- labelLarge: TextStyle(
- fontFamily: 'Inter',
- color: AppColors.lightTextPrimary,
- fontSize: 16,
- fontWeight: FontWeight.w600,
- ),
- labelMedium: TextStyle(
- fontFamily: 'Inter',
- color: AppColors.lightTextSecondary,
- fontSize: 12,
- fontWeight: FontWeight.w400,
- ),
- labelSmall: TextStyle(
- fontFamily: 'Inter',
- color: AppColors.lightTextDisabled,
- fontSize: 12,
- fontWeight: FontWeight.w400,
- ),
- ),
- );
- }
- }
|