我来帮你梳理 ColorScheme 中成对互补的颜色关系:

🎯 核心互补对(On 系列)

背景色前景色(互补)关系说明
primaryonPrimary主色背景 ↔ 主色上的文字/图标
primaryContaineronPrimaryContainer主色容器 ↔ 容器上的内容
secondaryonSecondary辅助色背景 ↔ 辅助色上的内容
secondaryContaineronSecondaryContainer辅助容器 ↔ 容器内容
tertiaryonTertiary点缀色背景 ↔ 点缀色上的内容
tertiaryContaineronTertiaryContainer点缀容器 ↔ 容器内容
erroronError错误背景 ↔ 错误上的内容
errorContaineronErrorContainer错误容器 ↔ 容器内容
surfaceonSurface表面背景 ↔ 表面主要内容
surfaceVariantonSurfaceVariant表面变体 ↔ 次要内容
backgroundonBackground页面背景 ↔ 页面内容
inverseSurfaceonInverseSurface反色表面 ↔ 反色内容

🎯 层级互补对(Surface 系列)

层级用途互补关系
surfaceDim最暗表面←→ surfaceBright 最亮表面
surfaceContainerLowest最低层容器←→ surfaceContainerHighest 最高层
surfaceContainerLow低层容器←→ surfaceContainerHigh 高层
surfaceContainer标准容器中间层级

层级逻辑:Lowest → Low → Container → High → Highest → Bright


🎯 固定色互补对(Fixed 系列)

固定背景固定前景说明
primaryFixedonPrimaryFixed不随主题变化的主色组合
primaryFixedDimonPrimaryFixedVariant深固定主色 ↔ 变体文字
secondaryFixedonSecondaryFixed固定辅助色组合
secondaryFixedDimonSecondaryFixedVariant深固定辅助色 ↔ 变体文字
tertiaryFixedonTertiaryFixed固定点缀色组合
tertiaryFixedDimonTertiaryFixedVariant深固定点缀色 ↔ 变体文字

🎯 效果互补对

效果用途互补关系
shadow阴影颜色←→ surface 被投影的表面
scrim遮罩层←→ surface 被遮罩的内容
outline主要边框←→ outlineVariant 次要边框
surfaceTint表面着色(叠加)←→ surface 被着色的表面

🎯 反色互补对(Inverse 系列)

正常模式反色模式关系
surface + onSurfaceinverseSurface + onInverseSurface正常表面 ↔ 反色表面
primaryinversePrimary正常主色 ↔ 反色主色

使用场景:

  • 正常:亮色背景 + 深色文字
  • 反色:深色背景 + 亮色文字(如 SnackBar)

📋 完整互补关系图

ColorScheme 互补结构
├── 主色组
│   ├── primary ↔ onPrimary
│   ├── primaryContainer ↔ onPrimaryContainer
│   └── primaryFixed ↔ onPrimaryFixed
│       └── primaryFixedDim ↔ onPrimaryFixedVariant
│
├── 辅助色组
│   ├── secondary ↔ onSecondary
│   ├── secondaryContainer ↔ onSecondaryContainer
│   └── secondaryFixed ↔ onSecondaryFixed
│       └── secondaryFixedDim ↔ onSecondaryFixedVariant
│
├── 点缀色组
│   ├── tertiary ↔ onTertiary
│   ├── tertiaryContainer ↔ onTertiaryContainer
│   └── tertiaryFixed ↔ onTertiaryFixed
│       └── tertiaryFixedDim ↔ onTertiaryFixedVariant
│
├── 错误色组
│   ├── error ↔ onError
│   └── errorContainer ↔ onErrorContainer
│
├── 表面层级组(递进关系)
│   ├── surfaceDim(最暗)→ ... → surfaceBright(最亮)
│   ├── surfaceContainerLowest → ... → surfaceContainerHighest
│   └── surface + onSurface(主要)
│       └── surfaceVariant + onSurfaceVariant(次要)
│
├── 背景组
│   └── background ↔ onBackground
│
├── 反色组(与正常相反)
│   ├── inverseSurface ↔ onInverseSurface
│   └── inversePrimary(对应 primary)
│
└── 效果组
    ├── shadow(投影)
    ├── scrim(遮罩)
    ├── outline ↔ outlineVariant(主次边框)
    └── surfaceTint(着色叠加到 surface)

💡 使用原则

原则说明
背景用 xxx,文字用 onXxx保证对比度
容器用 xxxContainer,内容用 onXxxContainer柔和背景配清晰文字
层级从 Lowest 到 Highest创建视觉深度
固定色不随主题变品牌标识保持一致
反色用于临时组件SnackBar、Toast 等

需要我把这些互补关系做成一个速查表代码吗?

参考代码 ,配色不好(待修改)
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../util/sp_util.dart';

///主题模式管理器 Create by lzx on 2020/3/11.

extension ThemeModeExtension on ThemeMode {
  String get value => ['System', 'Light', 'Dark'][index];
}

class ThemeProvider extends ChangeNotifier {
  /// 当前主题颜色
  // MaterialColor primarySwatch = Colors.orange;
  // MaterialColor primarySwatch = Colors.green;
  MaterialColor primarySwatch = Colors.blue;

  ThemeProvider() {
    loadFontSize();
  }

  double _fontSize = 1.0; // 默认字体大

  double get fontSize => _fontSize;

  double effectiveTextScaleFactor(BuildContext context) {
    // 获取系统的textScaleFactor,并结合用户设置的缩放比例
    return MediaQuery.of(context).textScaler.scale(_fontSize).clamp(0.6, 1.4);
  }

  Future<void> loadFontSize() async {
    final prefs = await SharedPreferences.getInstance();
    _fontSize = prefs.getDouble('fontSize') ?? 1.0;
    notifyListeners();
  }

  Future<void> saveFontSize(double size) async {
    final prefs = await SharedPreferences.getInstance();
    await prefs.setDouble('fontSize', size);
    _fontSize = size;
    notifyListeners();
  }

  void syncTheme() async {
    final String theme = SPUtil.getTheme();
    if (theme.isNotEmpty && theme != ThemeMode.system.value) {
      notifyListeners();
    }
  }

  void setTheme(ThemeMode themeMode) async {
    SPUtil.putTheme(themeMode.value);
    notifyListeners();
  }

  ThemeMode getThemeMode() {
    final String theme = SPUtil.getTheme();

    //print("当前$theme");
    switch (theme) {
      case 'Dark':
        return ThemeMode.dark;
      case 'Light':
        return ThemeMode.light;
      default:
        return ThemeMode.system;
    }
  }

  ThemeData getTheme({bool isDarkMode = false}) {
    final cs = _generateColorScheme(isDarkMode);

    return ThemeData(
      useMaterial3: true,
      brightness: isDarkMode ? Brightness.dark : Brightness.light,

      // ========== Material 3 核心配色 ==========
      colorScheme: cs,

      // ========== 兼容旧组件的基础颜色(全部与 ColorScheme 保持一致)==========
      primaryColor: cs.primary,
      primaryColorLight: primarySwatch.shade100,
      primaryColorDark: primarySwatch.shade700,

      // 背景系统
      scaffoldBackgroundColor: cs.background,
      // 页面主背景
      canvasColor: cs.surface,
      // 抽屉、底部弹窗背景
      cardColor: cs.surface,
      // 卡片背景
      dialogBackgroundColor: cs.surface,
      // 对话框背景
      dividerColor: cs.outlineVariant,
      // 分割线颜色

      // 状态颜色
      disabledColor: cs.onSurface.withOpacity(0.38),
      // 禁用态
      hintColor: cs.onSurfaceVariant,
      // 提示文字
      indicatorColor: cs.primary,
      // 指示器(Tab等)

      // 高亮/点击/悬浮/聚焦
      highlightColor: cs.primary.withOpacity(0.1),
      splashColor: cs.primary.withOpacity(0.1),
      hoverColor: cs.primary.withOpacity(0.05),
      focusColor: cs.primary.withOpacity(0.1),

      // 阴影
      shadowColor: cs.shadow,

      // 错误色(兼容旧组件)
      //errorColor: cs.error,

      // ==================== AppBar 主题 ====================
      appBarTheme: AppBarTheme(
        elevation: 0,
        scrolledUnderElevation: 3,
        backgroundColor: cs.surface,
        foregroundColor: cs.onSurface,
        surfaceTintColor: cs.surfaceTint,
        // systemOverlayStyle: isDarkMode
        //     ? SystemUiOverlayStyle.light
        //     : SystemUiOverlayStyle.dark,
        iconTheme: IconThemeData(color: cs.onSurface),
        actionsIconTheme: IconThemeData(color: cs.onSurface),
        titleTextStyle: TextStyle(
          fontSize: 20,
          fontWeight: FontWeight.w500,
          color: cs.onSurface,
        ),
      ),

      // ==================== Card 卡片主题 ====================
      cardTheme: CardTheme(
        elevation: 0,
        color: cs.surface,
        surfaceTintColor: cs.surfaceTint,
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(12),
        ),
      ),

      // ==================== 按钮系列(全部 M3 规范)====================
      elevatedButtonTheme: ElevatedButtonThemeData(
        style: ElevatedButton.styleFrom(
          foregroundColor: cs.onPrimary,
          backgroundColor: cs.primary,
          disabledForegroundColor: cs.onSurface.withOpacity(0.38),
          disabledBackgroundColor: cs.onSurface.withOpacity(0.12),
          elevation: 0,
          shadowColor: Colors.transparent,
          surfaceTintColor: Colors.transparent,
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(20),
          ),
          padding: EdgeInsets.symmetric(horizontal: 24, vertical: 12),
        ),
      ),

      filledButtonTheme: FilledButtonThemeData(
        style: FilledButton.styleFrom(
          foregroundColor: cs.onPrimary,
          backgroundColor: cs.primary,
          disabledForegroundColor: cs.onSurface.withOpacity(0.38),
          disabledBackgroundColor: cs.onSurface.withOpacity(0.12),
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(20),
          ),
          padding: EdgeInsets.symmetric(horizontal: 24, vertical: 12),
        ),
      ),

      outlinedButtonTheme: OutlinedButtonThemeData(
        style: OutlinedButton.styleFrom(
          foregroundColor: cs.primary,
          disabledForegroundColor: cs.onSurface.withOpacity(0.38),
          side: BorderSide(color: cs.outline),
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(20),
          ),
          padding: EdgeInsets.symmetric(horizontal: 24, vertical: 12),
        ),
      ),

      textButtonTheme: TextButtonThemeData(
        style: TextButton.styleFrom(
          foregroundColor: cs.primary,
          disabledForegroundColor: cs.onSurface.withOpacity(0.38),
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(20),
          ),
          padding: EdgeInsets.symmetric(horizontal: 12, vertical: 8),
        ),
      ),

      // ==================== 输入框样式 ====================
      inputDecorationTheme: InputDecorationTheme(
        filled: true,
        fillColor: cs.surfaceContainerHighest,
        contentPadding: EdgeInsets.symmetric(horizontal: 16, vertical: 12),
        border: OutlineInputBorder(
          borderRadius: BorderRadius.circular(12),
          borderSide: BorderSide.none,
        ),
        enabledBorder: OutlineInputBorder(
          borderRadius: BorderRadius.circular(12),
          borderSide: BorderSide.none,
        ),
        focusedBorder: OutlineInputBorder(
          borderRadius: BorderRadius.circular(12),
          borderSide: BorderSide(color: cs.primary, width: 2),
        ),
        errorBorder: OutlineInputBorder(
          borderRadius: BorderRadius.circular(12),
          borderSide: BorderSide(color: cs.error, width: 1),
        ),
        focusedErrorBorder: OutlineInputBorder(
          borderRadius: BorderRadius.circular(12),
          borderSide: BorderSide(color: cs.error, width: 2),
        ),
        disabledBorder: OutlineInputBorder(
          borderRadius: BorderRadius.circular(12),
          borderSide: BorderSide.none,
        ),
        labelStyle: TextStyle(color: cs.onSurfaceVariant),
        hintStyle: TextStyle(color: cs.onSurfaceVariant),
        prefixIconColor: cs.onSurfaceVariant,
        suffixIconColor: cs.onSurfaceVariant,
      ),

      // ==================== Chip 标签 ====================
      chipTheme: ChipThemeData(
        backgroundColor: cs.surfaceContainer,
        disabledColor: cs.onSurface.withOpacity(0.12),
        selectedColor: cs.secondaryContainer,
        secondarySelectedColor: cs.secondaryContainer,
        padding: EdgeInsets.symmetric(horizontal: 12, vertical: 4),
        shape: StadiumBorder(),
        labelStyle: TextStyle(color: cs.onSurface),
        secondaryLabelStyle: TextStyle(color: cs.onSecondaryContainer),
        brightness: cs.brightness,
        surfaceTintColor: cs.surfaceTint,
        deleteIconColor: cs.onSurfaceVariant,
      ),

      // ==================== 底部导航 ====================
      navigationBarTheme: NavigationBarThemeData(
        backgroundColor: cs.surfaceContainer,
        elevation: 0,
        height: 80,
        indicatorColor: cs.secondaryContainer,
        indicatorShape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(16),
        ),
        labelTextStyle: MaterialStateProperty.resolveWith((states) {
          if (states.contains(MaterialState.selected)) {
            return TextStyle(
              color: cs.onSurface,
              fontSize: 12,
              fontWeight: FontWeight.w500,
            );
          }
          return TextStyle(
            color: cs.onSurfaceVariant,
            fontSize: 12,
          );
        }),
        iconTheme: MaterialStateProperty.resolveWith((states) {
          if (states.contains(MaterialState.selected)) {
            return IconThemeData(color: cs.onSecondaryContainer);
          }
          return IconThemeData(color: cs.onSurfaceVariant);
        }),
      ),

      // ==================== 侧边导航 ====================
      navigationRailTheme: NavigationRailThemeData(
        backgroundColor: cs.surface,
        elevation: 0,
        selectedIconTheme: IconThemeData(color: cs.onSecondaryContainer),
        unselectedIconTheme: IconThemeData(color: cs.onSurfaceVariant),
        selectedLabelTextStyle: TextStyle(
          color: cs.onSurface,
          fontWeight: FontWeight.w500,
        ),
        unselectedLabelTextStyle: TextStyle(
          color: cs.onSurfaceVariant,
        ),
        indicatorColor: cs.secondaryContainer,
      ),

      // ==================== Tab 栏 ====================
      tabBarTheme: TabBarTheme(
        indicatorColor: cs.primary,
        indicatorSize: TabBarIndicatorSize.label,
        labelColor: cs.primary,
        unselectedLabelColor: cs.onSurfaceVariant,
        dividerColor: cs.outlineVariant,
      ),

      // ==================== 对话框 ====================
      dialogTheme: DialogTheme(
        backgroundColor: cs.surfaceContainerHigh,
        surfaceTintColor: cs.surfaceTint,
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(28),
        ),
      ),

      // ==================== 底部弹窗 ====================
      bottomSheetTheme: BottomSheetThemeData(
        backgroundColor: cs.surfaceContainerLow,
        surfaceTintColor: cs.surfaceTint,
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.vertical(top: Radius.circular(28)),
        ),
      ),

      // ==================== 提示条 SnackBar ====================
      snackBarTheme: SnackBarThemeData(
        backgroundColor: cs.inverseSurface,
        contentTextStyle: TextStyle(color: cs.onInverseSurface),
        actionTextColor: cs.inversePrimary,
        closeIconColor: cs.onInverseSurface,
        behavior: SnackBarBehavior.floating,
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(12),
        ),
      ),

      // ==================== 悬浮按钮 ====================
      floatingActionButtonTheme: FloatingActionButtonThemeData(
        foregroundColor: cs.onPrimaryContainer,
        backgroundColor: cs.primaryContainer,
        elevation: 0,
        focusElevation: 0,
        hoverElevation: 0,
        highlightElevation: 0,
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(16),
        ),
      ),

      // ==================== 开关 / 复选 / 单选 ====================
      switchTheme: SwitchThemeData(
        thumbColor: MaterialStateProperty.resolveWith((states) {
          if (states.contains(MaterialState.selected)) return cs.primary;
          if (states.contains(MaterialState.disabled))
            return cs.onSurface.withOpacity(0.38);
          return cs.outline;
        }),
        trackColor: MaterialStateProperty.resolveWith((states) {
          if (states.contains(MaterialState.selected))
            return cs.primary.withOpacity(0.5);
          return cs.surfaceVariant;
        }),
        trackOutlineColor: MaterialStateProperty.all(Colors.transparent),
      ),

      checkboxTheme: CheckboxThemeData(
        fillColor: MaterialStateProperty.resolveWith((states) {
          if (states.contains(MaterialState.selected)) return cs.primary;
          return Colors.transparent;
        }),
        checkColor: MaterialStateProperty.all(cs.onPrimary),
        side: BorderSide(color: cs.outline),
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(4),
        ),
      ),

      radioTheme: RadioThemeData(
        fillColor: MaterialStateProperty.resolveWith((states) {
          if (states.contains(MaterialState.selected)) return cs.primary;
          return cs.onSurfaceVariant;
        }),
      ),

      // ==================== 滑动条 ====================
      sliderTheme: SliderThemeData(
        activeTrackColor: cs.primary,
        inactiveTrackColor: cs.surfaceContainerHighest,
        thumbColor: cs.primary,
        overlayColor: cs.primary.withOpacity(0.1),
        valueIndicatorColor: cs.inverseSurface,
        valueIndicatorTextStyle: TextStyle(color: cs.onInverseSurface),
      ),

      // ==================== 进度条 ====================
      progressIndicatorTheme: ProgressIndicatorThemeData(
        color: cs.primary,
        linearTrackColor: cs.surfaceContainerHighest,
        circularTrackColor: cs.surfaceContainerHighest,
      ),

      // ==================== 分割线 ====================
      dividerTheme: DividerThemeData(
        color: cs.outlineVariant,
        thickness: 1,
        space: 1,
      ),

      // ==================== 列表项 ====================
      listTileTheme: ListTileThemeData(
        iconColor: cs.onSurfaceVariant,
        textColor: cs.onSurface,
        selectedColor: cs.primary,
        selectedTileColor: cs.primary.withOpacity(0.1),
        contentPadding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(12),
        ),
      ),

      // ==================== 提示框 ====================
      tooltipTheme: TooltipThemeData(
        decoration: BoxDecoration(
          color: cs.inverseSurface,
          borderRadius: BorderRadius.circular(8),
        ),
        textStyle: TextStyle(color: cs.onInverseSurface),
      ),

      // ==================== 文字主题 ====================
      textTheme: _buildTextTheme(isDarkMode, cs),

      // ==================== 图标主题 ====================
      iconTheme: IconThemeData(
        color: cs.onSurfaceVariant,
        size: 24,
      ),
      primaryIconTheme: IconThemeData(
        color: cs.onPrimary,
        size: 24,
      ),
    );
  }

  // ========== 生成完整的 ColorScheme ==========
  /// 根据 明暗模式 生成标准 Material3 ColorScheme
  ColorScheme _generateColorScheme(bool isDarkMode) {
    // ====================== 核心主色(基于你的 primarySwatch)======================
    final Color primary =
        isDarkMode ? primarySwatch.shade800 : primarySwatch.shade500;
    final Color onPrimary = isDarkMode
        ? Colors.white.withValues(alpha: 0.9)
        : Colors.white; // 主色上的文字 → 永远白色(最清晰)

    final Color primaryContainer = isDarkMode
        ? primarySwatch.shade800 // 暗黑:深容器
        : primarySwatch.shade100; // 亮色:浅容器

    final Color onPrimaryContainer = isDarkMode
        ? primarySwatch.shade200 // 暗黑容器上的文字 → 亮色
        : primarySwatch.shade700; // 亮色容器上的文字 → 暗色

    // ====================== 辅助色 Secondary(柔和、不抢戏)======================
    final Color secondary =
        isDarkMode ? Colors.blueGrey.shade300 : Colors.blueGrey.shade500;

    final Color onSecondary = Colors.white;

    final Color secondaryContainer =
        isDarkMode ? Colors.blueGrey.shade700 : Colors.blueGrey.shade100;

    final Color onSecondaryContainer =
        isDarkMode ? Colors.blueGrey.shade200 : Colors.blueGrey.shade700;

    // ====================== 第三色 Tertiary(点缀色)======================
    final Color tertiary =
        isDarkMode ? primarySwatch.shade200 : primarySwatch.shade400;

    final Color onTertiary = Colors.white;

    final Color tertiaryContainer =
        isDarkMode ? primarySwatch.shade700 : primarySwatch.shade50;

    final Color onTertiaryContainer =
        isDarkMode ? primarySwatch.shade200 : primarySwatch.shade600;

    // ====================== 错误色(系统标准,不自己乱配)======================
    final Color error = isDarkMode ? Colors.red.shade400 : Colors.red.shade600;
    final Color onError = Colors.white;
    final Color errorContainer =
        isDarkMode ? Colors.red.shade800 : Colors.red.shade100;
    final Color onErrorContainer =
        isDarkMode ? Colors.red.shade200 : Colors.red.shade800;

    // ====================== 背景 / 表面色(M3 标准灰度,干净舒适)======================
    final Color background =
        isDarkMode ? const Color(0xFF141218) : const Color(0xFFF8F9FA);
    final Color onBackground =
        isDarkMode ? const Color(0xFFE1E1E1) : const Color(0xFF1A1A1A);

    final Color surface =
        isDarkMode ? const Color(0xFF1B1A1F) : const Color(0xFFFFFFFF);
    final Color onSurface =
        isDarkMode ? const Color(0xFFE1E1E1) : const Color(0xFF1A1A1A);

    final Color surfaceVariant =
        isDarkMode ? const Color(0xFF45464F) : const Color(0xFFE0E2E8);
    final Color onSurfaceVariant =
        isDarkMode ? const Color(0xFFC4C6CF) : const Color(0xFF45464F);

    // Surface 层级(卡片、弹窗、对话框 自动分层)
    final Color surfaceDim =
        isDarkMode ? const Color(0xFF141218) : const Color(0xFFE0E2E8);
    final Color surfaceBright =
        isDarkMode ? const Color(0xFF35363F) : const Color(0xFFFFFFFF);
    final Color surfaceContainerLowest =
        isDarkMode ? const Color(0xFF0C0C0F) : const Color(0xFFFFFFFF);
    final Color surfaceContainerLow =
        isDarkMode ? const Color(0xFF1F1F24) : const Color(0xFFF5F7FA);
    final Color surfaceContainer =
        isDarkMode ? const Color(0xFF24252A) : const Color(0xFFF0F2F5);
    final Color surfaceContainerHigh =
        isDarkMode ? const Color(0xFF2B2C31) : const Color(0xFFE9EBF0);
    final Color surfaceContainerHighest =
        isDarkMode ? const Color(0xFF323338) : const Color(0xFFE1E3E8);

    // ====================== 边框 / 轮廓(柔和、不刺眼)======================
    final Color outline =
        isDarkMode ? Colors.grey.shade600 : Colors.grey.shade400;
    final Color outlineVariant =
        isDarkMode ? Colors.grey.shade700 : Colors.grey.shade300;

    // ====================== 反色 / 遮罩 / 阴影(系统标准)======================
    final Color inverseSurface =
        isDarkMode ? const Color(0xFFE1E1E1) : const Color(0xFF2A2A2F);
    final Color onInverseSurface =
        isDarkMode ? const Color(0xFF1B1A1F) : const Color(0xFFFFFFFF);
    final Color inversePrimary =
        isDarkMode ? primarySwatch.shade400 : primarySwatch.shade200;

    final Color shadow = Colors.black;
    final Color scrim = Colors.black.withOpacity(0.6);
    final Color surfaceTint = primary;

    // ====================== 返回完整 ColorScheme ======================
    return ColorScheme(
      // ========== 基础亮度设置 ==========
      brightness: isDarkMode ? Brightness.dark : Brightness.light,
      // 作用:告知 Flutter 当前是亮色还是暗色模式
      // 影响:MediaQuery.platformBrightness、StatusBar 图标颜色等系统级渲染

      // ========== 主色系列(Primary)- 品牌主色调 ==========

      /// 主色 - 最重要的品牌色
      /// 使用组件:
      /// - ElevatedButton(填充按钮背景)
      /// - FloatingActionButton(FAB 背景,如果未设置专门主题)
      /// - ProgressIndicator(进度条颜色)
      /// - Switch 开启状态(滑块颜色)
      /// - Checkbox 选中状态(填充色)
      /// - Radio 选中状态(圆点颜色)
      /// - Slider 激活轨道(已滑过部分)
      /// - TabBar 指示器(下划线)
      /// - NavigationBar 选中图标(如果未覆盖)
      /// - 链接文字、可点击文字
      /// - AppBar 操作按钮(如果 foregroundColor 未设置)
      primary: primary,

      /// 主色上的文字/图标颜色 - 确保在主色背景上可读
      /// 使用组件:
      /// - ElevatedButton 上的文字
      /// - FilledButton 上的文字
      /// - FloatingActionButton 上的图标
      /// - SnackBar 操作按钮文字(如果未使用 inverse)
      /// - 任何 primary 色背景上的内容
      onPrimary: onPrimary,

      /// 主色容器 - 比主色更柔和的背景
      /// 使用组件:
      /// - FloatingActionButton(M3 默认使用,比旧版 primary 更柔和)
      /// - Chip(选中状态的背景)
      /// - 需要强调但不刺眼的区域背景
      /// - 关键数据卡片、重要信息容器
      primaryContainer: primaryContainer,

      /// 主色容器上的文字/图标颜色
      /// 使用组件:
      /// - FloatingActionButton 上的图标(M3 样式)
      /// - Chip 选中状态下的文字
      /// - primaryContainer 背景上的所有内容
      onPrimaryContainer: onPrimaryContainer,

      // ========== 辅助色系列(Secondary)- 次要操作 ==========

      /// 辅助色 - 用于次要操作和组件
      /// 使用组件:
      /// - OutlinedButton 文字和边框(如果未专门设置)
      /// - TextButton 文字颜色(如果未专门设置)
      /// - ToggleButtons 选中状态
      /// - FilterChip、ChoiceChip 选中状态
      /// - 次要操作按钮、备选操作
      /// - 标签、分类标识
      secondary: secondary,

      /// 辅助色上的文字/图标颜色
      /// 使用组件:
      /// - 任何 secondary 色背景上的文字和图标
      onSecondary: onSecondary,

      /// 辅助色容器 - 柔和的背景色
      /// 使用组件:
      /// - NavigationBar 选中指示器背景(那个圆形高亮)
      /// - NavigationRail 选中指示器
      /// - Chip 默认背景(未选中状态)
      /// - 次要信息卡片、标签容器
      /// - 筛选器、分类标签背景
      secondaryContainer: secondaryContainer,

      /// 辅助色容器上的文字/图标颜色
      /// 使用组件:
      /// - NavigationBar 选中项的图标和文字
      /// - NavigationRail 选中项的图标和文字
      /// - Chip 上的文字
      /// - secondaryContainer 背景上的所有内容
      onSecondaryContainer: onSecondaryContainer,

      // ========== 点缀色系列(Tertiary)- 对比平衡 ==========

      /// 点缀色 - 用于需要对比强调的元素
      /// 使用组件:
      /// - 特殊强调按钮(不同于主次操作)
      /// - 促销标签、限时活动标识
      /// - 新功能引导标记
      /// - 与主色形成对比的强调元素
      /// - 第三方登录按钮等特殊操作
      tertiary: tertiary,

      /// 点缀色上的文字/图标颜色
      /// 使用组件:
      /// - 任何 tertiary 色背景上的内容
      onTertiary: onTertiary,

      /// 点缀色容器 - 柔和的背景
      /// 使用组件:
      /// - 特殊标签背景
      /// - 促销卡片背景
      /// - 新功能提示框
      /// - 需要与主色、次色区分的强调容器
      tertiaryContainer: tertiaryContainer,

      /// 点缀色容器上的文字/图标颜色
      /// 使用组件:
      /// - tertiaryContainer 背景上的所有内容
      onTertiaryContainer: onTertiaryContainer,

      // ========== 错误色系列(Error)- 警告和错误状态 ==========

      /// 错误色 - 表示错误、删除、警告
      /// 使用组件:
      /// - TextField 错误状态下的边框和图标
      /// - Form 验证错误提示
      /// - 删除按钮、危险操作
      /// - 错误提示图标
      /// - 必填项标记(红色星号)
      /// - 系统错误状态指示
      error: error,

      /// 错误色上的文字/图标颜色(通常是白色)
      /// 使用组件:
      /// - 错误按钮上的文字
      /// - 错误图标上的内容
      onError: onError,

      /// 错误色容器 - 柔和的错误背景
      /// 使用组件:
      /// - 错误提示卡片背景
      /// - 删除确认对话框背景
      /// - 表单错误信息区域背景
      /// - 警告提示框背景
      errorContainer: errorContainer,

      /// 错误色容器上的文字颜色
      /// 使用组件:
      /// - 错误提示卡片内的文字
      /// - errorContainer 背景上的所有内容
      onErrorContainer: onErrorContainer,

      // ========== 背景色系列(Background)- 页面级背景 ==========

      /// 页面背景色 - 最底层的背景
      /// 使用组件:
      /// - Scaffold 背景(如果 scaffoldBackgroundColor 未设置)
      /// - 页面底层背景
      /// - 大面积区域背景
      /// 注意:实际 Scaffold 通常使用 scaffoldBackgroundColor,需要单独设置
      background: background,

      /// 背景上的文字/图标颜色
      /// 使用组件:
      /// - 页面上的主要文字
      /// - 背景色上的图标
      /// - 与 background 形成对比的内容
      onBackground: onBackground,

      // ========== 表面色系列(Surface)- 组件级背景 ==========

      /// 表面色 - 组件的默认背景
      /// 使用组件:
      /// - Card 默认背景(如果 cardColor 未设置)
      /// - Dialog 背景(如果 dialogBackgroundColor 未设置)
      /// - BottomSheet 背景
      /// - Drawer 背景(配合 canvasColor)
      /// - 任何需要浮于背景之上的表面
      /// 注意:实际组件可能读取专门的主题属性,需要同时设置
      surface: surface,

      /// 表面上的文字/图标颜色 - 主要内容色
      /// 使用组件:
      /// - Card 内的标题和正文
      /// - Dialog 内的文字
      /// - ListTile 标题和副标题
      /// - 表面色背景上的主要内容
      onSurface: onSurface,

      /// 表面变体色 - 用于区分层级
      /// 使用组件:
      /// - 旧版组件的背景区分
      /// - 需要与 surface 微妙区分的区域
      /// - 某些 M2 组件的替代背景
      /// 注意:M3 中逐渐被 surfaceContainer 系列取代
      surfaceVariant: surfaceVariant,

      /// 表面变体上的文字颜色 - 次要内容
      /// 使用组件:
      /// - 辅助文字、说明文字
      /// - 图标(未激活状态)
      /// - 占位符文字、提示信息
      /// - 比 onSurface 优先级低的内容
      onSurfaceVariant: onSurfaceVariant,

      /// 暗表面色 - 最暗的表面层级
      /// 使用组件:
      /// - 底部区域、底层卡片
      /// - 需要下沉视觉层级的区域
      /// - 深色模式下的某些背景
      surfaceDim: surfaceDim,

      /// 亮表面色 - 最亮的表面层级
      /// 使用组件:
      /// - 顶部区域、主要卡片
      /// - 需要提升视觉层级的区域
      /// - 亮色模式下的主要表面
      surfaceBright: surfaceBright,

      /// 表面容器最低层 - 最底层的容器
      /// 使用组件:
      /// - 页面最底层容器(如底部导航栏下方)
      /// - 与背景融合的区域
      /// - 最低层级的卡片堆叠
      surfaceContainerLowest: surfaceContainerLowest,

      /// 表面容器低层 - 较低层级
      /// 使用组件:
      /// - 底部导航栏背景(NavigationBar)
      /// - 较低层级的卡片
      /// - 次要信息区域
      surfaceContainerLow: surfaceContainerLow,

      /// 表面容器默认层 - 标准容器背景
      /// 使用组件:
      /// - Card 背景(M3 推荐)
      /// - 标准对话框背景
      /// - 主要内容卡片
      /// - 中等层级的容器
      surfaceContainer: surfaceContainer,

      /// 表面容器高层 - 较高层级
      /// 使用组件:
      /// - 悬浮卡片、展开面板
      /// - 侧边栏、导航抽屉
      /// - 需要突出显示的区域
      surfaceContainerHigh: surfaceContainerHigh,

      /// 表面容器最高层 - 最顶层
      /// 使用组件:
      /// - 顶部应用栏(AppBar 备选)
      /// - 模态对话框、警告框
      /// - 最高层级的弹出内容
      /// - 需要最强分离感的区域
      surfaceContainerHighest: surfaceContainerHighest,

      // ========== 轮廓色系列(Outline)- 边框和分隔 ==========

      /// 轮廓色 - 主要边框颜色
      /// 使用组件:
      /// - OutlinedButton 边框
      /// - TextField 未聚焦边框
      /// - Card 边框(如果设置)
      /// - Divider 分割线(如果 dividerColor 未设置)
      /// - 组件边界线、分隔线
      outline: outline,

      /// 轮廓变体色 - 次要边框,更柔和
      /// 使用组件:
      /// - 细分割线
      /// - 弱化边框
      /// - 禁用状态的边框
      /// - 不明显的分隔线
      outlineVariant: outlineVariant,

      // ========== 效果色系列(Effects)- 阴影和遮罩 ==========

      /// 阴影色 - 组件阴影
      /// 使用组件:
      /// - Card 阴影(有 elevation 时)
      /// - AppBar 阴影
      /// - FloatingActionButton 阴影
      /// - 任何带 elevation 组件的阴影
      /// 注意:通常是半透明黑色,而非纯黑
      shadow: shadow,

      /// 遮罩色 - 模态背后的遮罩
      /// 使用组件:
      /// - Dialog 背后的半透明层
      /// - BottomSheet 展开时的背景遮罩
      /// - Modal 遮罩
      /// - 引导页遮罩、高亮遮罩
      scrim: scrim,

      // ========== 反色系列(Inverse)- 深色背景上的亮色 ==========

      /// 反表面色 - 用于深色组件的亮色背景
      /// 使用组件:
      /// - SnackBar 背景(默认使用,在深色背景上显示亮色)
      /// - 底部出现的提示条
      /// - 临时通知、轻量提示
      /// - 需要与页面形成强烈对比的组件
      inverseSurface: inverseSurface,

      /// 反表面上的文字颜色 - 深色文字
      /// 使用组件:
      /// - SnackBar 内的文字
      /// - 任何 inverseSurface 背景上的内容
      onInverseSurface: onInverseSurface,

      /// 反主色 - 深色背景上的主色调
      /// 使用组件:
      /// - SnackBar 操作按钮文字("撤销"等)
      /// - inverseSurface 背景上的强调色
      /// - 深色卡片上的链接、按钮
      inversePrimary: inversePrimary,

      // ========== 表面着色(Surface Tint)- M3 特性 ==========

      /// 表面着色 - 给 elevation 添加品牌色调
      /// 使用组件:
      /// - 所有带 elevation 的 M3 组件
      /// - Card 阴影着色(elevation > 0 时)
      /// - AppBar 滚动时的颜色变化(scrolledUnderElevation)
      /// - Dialog、BottomSheet 的阴影着色
      /// - 让灰色阴影带有品牌色调,增强品牌感
      /// 原理:将主色混合到阴影中,elevation 越高着色越明显
      surfaceTint: surfaceTint,

      // ========== 固定色系列(Fixed)- 不随主题变化的品牌色 ==========

      /// 固定主色容器 - 始终保持柔和主色
      /// 使用组件:
      /// - 品牌标识区域
      /// - 需要保持品牌识别度的固定元素
      /// - 广告横幅、品牌展示区
      /// - 不随明暗模式变化的关键品牌元素
      /// 特点:在明暗模式下保持相同的视觉感受
      primaryFixed: primaryContainer,

      /// 暗固定主色 - 较深的固定主色
      /// 使用组件:
      /// - 固定品牌元素的深色变体
      /// - 需要层次感的固定品牌区域
      primaryFixedDim: primary,

      /// 固定主色上的文字
      /// 使用组件:
      /// - primaryFixed 背景上的内容
      onPrimaryFixed: onPrimaryContainer,

      /// 固定主色变体文字
      /// 使用组件:
      /// - primaryFixed 上的次要文字
      onPrimaryFixedVariant: onPrimary,

      /// 固定辅助色容器
      /// 使用组件:
      /// - 次要品牌元素的固定背景
      /// - 辅助系统标识
      secondaryFixed: secondaryContainer,

      /// 暗固定辅助色
      secondaryFixedDim: secondary,

      /// 固定辅助色上的文字
      onSecondaryFixed: onSecondaryContainer,

      /// 固定辅助色变体文字
      onSecondaryFixedVariant: onSecondary,

      /// 固定点缀色容器
      /// 使用组件:
      /// - 点缀品牌元素的固定背景
      tertiaryFixed: tertiaryContainer,

      /// 暗固定点缀色
      tertiaryFixedDim: tertiary,

      /// 固定点缀色上的文字
      onTertiaryFixed: onTertiaryContainer,

      /// 固定点缀色变体文字
      onTertiaryFixedVariant: onTertiary,
    );
  }

  // ========== 构建文字主题(集成 ColorScheme)==========
  TextTheme _buildTextTheme(bool isDarkMode, ColorScheme cs) {
    // 基础样式,你可以替换为你的 TextStyles
    final baseStyle = TextStyle(
      color: cs.onSurface,
      fontFamily: 'Roboto', // 或你的字体
    );

    return TextTheme(
      // Display
      displayLarge: baseStyle.copyWith(
          fontSize: 57,
          fontWeight: FontWeight.w400,
          letterSpacing: -0.25,
          color: cs.onSurface),
      displayMedium: baseStyle.copyWith(
          fontSize: 45,
          fontWeight: FontWeight.w400,
          letterSpacing: 0,
          color: cs.onSurface),
      displaySmall: baseStyle.copyWith(
          fontSize: 36,
          fontWeight: FontWeight.w400,
          letterSpacing: 0,
          color: cs.onSurface),

      // Headline
      headlineLarge: baseStyle.copyWith(
          fontSize: 32,
          fontWeight: FontWeight.w400,
          letterSpacing: 0,
          color: cs.onSurface),
      headlineMedium: baseStyle.copyWith(
          fontSize: 28,
          fontWeight: FontWeight.w400,
          letterSpacing: 0,
          color: cs.onSurface),
      headlineSmall: baseStyle.copyWith(
          fontSize: 24,
          fontWeight: FontWeight.w400,
          letterSpacing: 0,
          color: cs.onSurface),

      // Title
      titleLarge: baseStyle.copyWith(
          fontSize: 22,
          fontWeight: FontWeight.w400,
          letterSpacing: 0,
          color: cs.onSurface),
      titleMedium: baseStyle.copyWith(
          fontSize: 16,
          fontWeight: FontWeight.w500,
          letterSpacing: 0.15,
          color: cs.onSurface),
      titleSmall: baseStyle.copyWith(
          fontSize: 14,
          fontWeight: FontWeight.w500,
          letterSpacing: 0.1,
          color: cs.onSurface),

      // Body
      bodyLarge: baseStyle.copyWith(
          fontSize: 16,
          fontWeight: FontWeight.w400,
          letterSpacing: 0.5,
          color: cs.onSurface),
      bodyMedium: baseStyle.copyWith(
          fontSize: 14,
          fontWeight: FontWeight.w400,
          letterSpacing: 0.25,
          color: cs.onSurface),
      bodySmall: baseStyle.copyWith(
          fontSize: 12,
          fontWeight: FontWeight.w400,
          letterSpacing: 0.4,
          color: cs.onSurfaceVariant),

      // Label
      labelLarge: baseStyle.copyWith(
          fontSize: 14,
          fontWeight: FontWeight.w500,
          letterSpacing: 0.1,
          color: cs.primary),
      labelMedium: baseStyle.copyWith(
          fontSize: 12,
          fontWeight: FontWeight.w500,
          letterSpacing: 0.5,
          color: cs.onSurfaceVariant),
      labelSmall: baseStyle.copyWith(
          fontSize: 11,
          fontWeight: FontWeight.w500,
          letterSpacing: 0.5,
          color: cs.onSurfaceVariant),
    );
  }
}

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐