Skip to content

Songloft 颜色系统规范

本文档说明 Songloft 项目中使用的颜色体系及其使用规范。

📚 目录


Flutter Material 3 颜色体系

Songloft Flutter 前端使用 Material 3 设计系统,通过 ColorScheme.fromSeed 自动生成完整的颜色方案。

核心配置

dart
// songloft-player/lib/core/theme/app_theme.dart
class AppTheme {
  static const Color _seedColor = Color(0xFF6366F1); // indigo-500

  static ThemeData lightTheme({ScreenType screenType = ScreenType.mobile}) {
    return _buildTheme(Brightness.light, screenType);
  }

  static ThemeData darkTheme({ScreenType screenType = ScreenType.mobile}) {
    return _buildTheme(Brightness.dark, screenType);
  }
}

优势

  1. 自动配色:从 seed color 自动生成完整的亮色/暗色配色方案
  2. 语义化角色primarysecondarytertiaryerror 等语义化颜色角色
  3. 对比度保证:Material 3 自动确保文本与背景的对比度符合无障碍标准
  4. 一致性:所有组件自动使用统一的配色方案

ColorScheme 颜色角色

角色用途示例
primary主要操作、强调元素播放按钮、导航选中态
onPrimaryprimary 上的文本/图标按钮文字
primaryContainer主色容器背景选中卡片背景
secondary次要操作辅助按钮
tertiary第三级强调标签、徽章
error错误状态删除按钮、错误提示
surface页面/卡片背景Scaffold 背景
onSurfacesurface 上的文本主要文本
onSurfaceVariant次要文本副标题、说明文字
outline边框输入框边框、分割线
outlineVariant弱化边框列表分割线

主题配置

主题模式

Songloft 支持三种主题模式:

  • 亮色模式:明亮的界面风格
  • 暗色模式:护眼的暗色界面
  • 跟随系统:自动跟随操作系统设置

主题切换通过 ThemeSelector 组件实现,状态由 themeModeProvider 管理。

字体配置

dart
ThemeData(
  fontFamilyFallback: const ['NotoSansSC', 'sans-serif'],
  // ...
)
  • 默认使用系统字体
  • 中文回退到 Noto Sans SC(随应用打包)

组件主题定制

dart
ThemeData(
  useMaterial3: true,
  appBarTheme: const AppBarTheme(centerTitle: false, elevation: 0),
  cardTheme: CardThemeData(elevation: 0, shape: RoundedRectangleBorder(...)),
  inputDecorationTheme: InputDecorationTheme(border: OutlineInputBorder(...), filled: true),
  navigationBarTheme: const NavigationBarThemeData(height: 64, ...),
  // ...
)

颜色使用规范

✅ 推荐使用

1. 通过 Theme 获取颜色

dart
// 获取 ColorScheme
final colorScheme = Theme.of(context).colorScheme;

// 主色
Container(color: colorScheme.primary)
Text('标题', style: TextStyle(color: colorScheme.onSurface))

// 次要文本
Text('描述', style: TextStyle(color: colorScheme.onSurfaceVariant))

// 错误状态
Icon(Icons.error, color: colorScheme.error)

2. 使用 TextTheme

dart
final textTheme = Theme.of(context).textTheme;

Text('大标题', style: textTheme.headlineMedium)
Text('正文', style: textTheme.bodyLarge)
Text('说明', style: textTheme.bodySmall)

3. 使用 Material 组件的内置颜色

dart
// FilledButton 自动使用 primary 色
FilledButton(onPressed: () {}, child: Text('主要操作'))

// OutlinedButton 自动使用 outline 色
OutlinedButton(onPressed: () {}, child: Text('次要操作'))

// TextButton 自动使用 primary 色
TextButton(onPressed: () {}, child: Text('文本操作'))

❌ 避免使用

dart
// 不要硬编码颜色值
Container(color: Color(0xFF6366F1))  // ❌

// 不要使用 Colors 常量(不跟随主题)
Text('文本', style: TextStyle(color: Colors.grey))  // ❌

// 应该使用 Theme
Container(color: Theme.of(context).colorScheme.primary)  // ✅
Text('文本', style: TextStyle(color: Theme.of(context).colorScheme.onSurfaceVariant))  // ✅

响应式主题适配

主题根据屏幕类型(Mobile / Tablet / Desktop / TV)动态调整组件尺寸:

SnackBar

屏幕类型样式
Mobile默认浮动样式
Desktop固定宽度 480px,居中
TV固定宽度 600px,更大内边距

FilledButton

屏幕类型最小尺寸
非 TV(Mobile / Tablet / Desktop)88 × 44
TV120 × 56

实际代码 (app_theme.dart) 只按 isTv 分两档;Mobile / Tablet / Desktop 共用 88×44。

对话框最大宽度

屏幕类型最大宽度
Mobile300px
Tablet400px
Desktop480px
TV600px

TV 端专用尺寸

TV 端使用 TvTheme 类定义的专用常量:

属性说明
标题字体24spfontSizeTitle
正文字体20spfontSizeBody
副标题字体16spfontSizeCaption
焦点边框4pxfocusBorderWidth
焦点缩放1.05xfocusScale
网格列数4gridColumns
内容内边距48pxcontentPadding

封面颜色提取

Songloft 使用 palette_generator 库从歌曲封面图片中提取主色调,用于播放器界面的动态配色:

dart
// songloft-player/lib/core/utils/color_extraction.dart
// 从封面图片提取主色调,应用到播放器背景渐变等场景

更新日志

  • 2026-04-14: 更新为 Flutter Material 3 颜色体系
    • 主前端迁移到 Flutter,使用 ColorScheme.fromSeed 自动配色
    • seedColor: indigo-500 (#6366F1)
    • 新增响应式主题适配(Mobile / Tablet / Desktop / TV)
    • 新增 TV 端专用主题常量(TvTheme
    • 新增封面颜色提取功能