鸿蒙Flutter实战:Material 3种子色亮暗双主题系统
2026/6/3 23:22:56 网站建设 项目流程

前言

Flutter 3.x 开始,Material 3(M3)成为默认设计语言。相比 Material 2,M3 最大的变化之一是动态配色——通过一个"种子色",自动生成整个应用的色调系统,包括主色、次要色、表面色、错误色,以及它们在不同亮度等级下的变体。

鸿蒙 Flutter 备忘录使用薄荷绿#4DB6AC作为种子色,同时支持亮色和暗色双主题,跟随系统设置自动切换。本文拆解这套主题系统的设计和实现。

项目仓库:todo_flutter_harmony

为什么是 ColorScheme.fromSeed

Material 2 时代,开发者需要手动定义 8-12 个颜色值来构建一个完整的主题:

// Material 2 —— 繁琐ThemeData(primaryColor:Color(0xFF4DB6AC),primaryColorLight:Color(0xFF80CBC4),primaryColorDark:Color(0xFF00897B),accentColor:Color(0xFFFF8A65),// ... 还要 backgroundColor, surfaceColor, errorColor 等等)

Material 3 的ColorScheme.fromSeed让你只需要一个颜色:

// Material 3 —— 简洁ThemeData(colorScheme:ColorScheme.fromSeed(seedColor:constColor(0xFF4DB6AC),brightness:Brightness.light,),)

fromSeed内部使用基于 HCT(Hue-Chroma-Tone)色彩空间的算法,自动生成 30+ 个色调变体。这个算法由 Google 的 Material Design 团队开发,考虑了人眼对不同色调的敏感度差异,生成的色板在任何组合下都能保持足够的对比度。

App 入口:ThemeMode 和 ThemeData

classAppextendsStatefulWidget{@overrideState<App>createState()=>_AppState();}class_AppStateextendsState<App>{@overrideWidgetbuild(BuildContextcontext){returnMaterialApp(title:'芯捷备忘录',debugShowCheckedModeBanner:false,themeMode:ThemeMode.system,// 跟随系统设置theme:_buildLightTheme(),darkTheme:_buildDarkTheme(),home:constHomePage(),onGenerateRoute:_generateRoute,);}
  • themeMode: ThemeMode.system:应用自动跟随系统的亮/暗模式设置
  • theme:系统为亮色模式时的主题
  • darkTheme:系统为暗色模式时的主题

如果想让用户手动控制(而不是跟随系统),可以换成:

themeMode:ThemeMode.light,// 始终亮色themeMode:ThemeMode.dark,// 始终暗色

亮色主题

ThemeData_buildLightTheme(){finalcolorScheme=ColorScheme.fromSeed(seedColor:constColor(0xFF4DB6AC),// 薄荷绿brightness:Brightness.light,);returnThemeData(useMaterial3:true,colorScheme:colorScheme,appBarTheme:AppBarTheme(centerTitle:true,backgroundColor:colorScheme.surface,foregroundColor:colorScheme.onSurface,elevation:0,scrolledUnderElevation:1,),cardTheme:CardTheme(elevation:1.0,shadowColor:colorScheme.shadow.withOpacity(0.3),shape:RoundedRectangleBorder(borderRadius:BorderRadius.circular(16),),clipBehavior:Clip.antiAlias,),navigationBarTheme:NavigationBarThemeData(elevation:2,indicatorColor:colorScheme.primaryContainer,surfaceTintColor:colorScheme.surfaceTint,),floatingActionButtonTheme:FloatingActionButtonThemeData(backgroundColor:colorScheme.primaryContainer,foregroundColor:colorScheme.onPrimaryContainer,elevation:4,),inputDecorationTheme:InputDecorationTheme(border:OutlineInputBorder(borderRadius:BorderRadius.circular(12),),contentPadding:constEdgeInsets.symmetric(horizontal:16,vertical:14),),snackBarTheme:SnackBarThemeData(behavior:SnackBarBehavior.floating,shape:RoundedRectangleBorder(borderRadius:BorderRadius.circular(10)),),);}

暗色主题

ThemeData_buildDarkTheme(){finalcolorScheme=ColorScheme.fromSeed(seedColor:constColor(0xFF4DB6AC),brightness:Brightness.dark,);returnThemeData(useMaterial3:true,colorScheme:colorScheme,appBarTheme:AppBarTheme(centerTitle:true,backgroundColor:colorScheme.surface,foregroundColor:colorScheme.onSurface,elevation:0,scrolledUnderElevation:1,),cardTheme:CardTheme(elevation:1.0,shadowColor:Colors.black.withOpacity(0.3),shape:RoundedRectangleBorder(borderRadius:BorderRadius.circular(16),),clipBehavior:Clip.antiAlias,),// ... 其余与亮色主题一致);}

注意暗色主题用Brightness.dark——ColorScheme.fromSeed会基于这个参数自动调整色调的明暗层级。同一个色值#4DB6AC在 HCT 色彩空间中的表现会因亮度不同而变化。

在组件中使用 ColorScheme

在具体组件中,通过Theme.of(context).colorScheme获取颜色:

classMemoCardextendsStatelessWidget{finalMemomemo;@overrideWidgetbuild(BuildContextcontext){finalcolors=Theme.of(context).colorScheme;returnCard(color:colors.surface,child:ListTile(title:Text(memo.title,style:TextStyle(color:colors.onSurface)),subtitle:Text(memo.content,style:TextStyle(color:colors.onSurfaceVariant)),trailing:Icon(memo.isPinned?Icons.push_pin:null,color:colors.primary,),),);}}

常用 colorScheme 属性速查:

属性用途
primary主色,用于高亮交互元素
onPrimary主色上的文字颜色
primaryContainer主色的容器背景(比主色浅)
secondary次要色
surface卡片、AppBar 等表面色
onSurface表面上的文字颜色
onSurfaceVariant表面上的次要文字(灰色调)
error错误提示色
surfaceTint表面色调

关键规则coloronColor成对使用。如果背景是surface,文字就是onSurface。这个命名约定在 Material 3 的文档中被严格执行。

ColorScheme 的 HCT 色彩空间

ColorScheme.fromSeed使用 HCT 而非传统的 HSL/RGB 色彩空间。HCT 的三个维度:

  • Hue(色相):与 HSL 的色相相同
  • Chroma(色度/饱和度):颜色的鲜艳程度
  • Tone(亮度):从 0(黑)到 100(白)

HCT 的关键优势是感知均匀度——在 RGB 空间中看起来"亮度一致"的两个颜色,在人眼感知下可能分别偏亮和偏暗。HCT 修正了这个问题,让生成的色调在感知上真正一致。

对开发者来说,这意味着ColorScheme.fromSeed生成的色板在所有亮度层级下都具有足够的 WCAG 对比度,无需手动调整。Material 3 的颜色生成算法会自动保证可访问性。

皮肤页面(SkinPage)

应用预留了一个皮肤设置页面,允许用户在亮色/暗色/跟随系统之间手动切换。核心代码:

classSkinPageextendsStatelessWidget{@overrideWidgetbuild(BuildContextcontext){finalcurrentMode=context.watch<ThemeProvider>().themeMode;returnScaffold(appBar:AppBar(title:constText('主题设置')),body:ListView(children:[RadioListTile<ThemeMode>(title:constText('浅色模式'),value:ThemeMode.light,groupValue:currentMode,onChanged:(mode)=>context.read<ThemeProvider>().setThemeMode(mode!),),RadioListTile<ThemeMode>(title:constText('深色模式'),value:ThemeMode.dark,groupValue:currentMode,onChanged:(mode)=>context.read<ThemeProvider>().setThemeMode(mode!),),RadioListTile<ThemeMode>(title:constText('跟随系统'),value:ThemeMode.system,groupValue:currentMode,onChanged:(mode)=>context.read<ThemeProvider>().setThemeMode(mode!),),],),);}}

实现用户手动切换需要将ThemeMode提升为一个可持久化的状态:

classThemeProviderextendsChangeNotifier{ThemeMode_themeMode=ThemeMode.system;ThemeModegetthemeMode=>_themeMode;Future<void>loadThemeMode()async{// 从文件/SharedPreferences 读取用户偏好finalsaved=await_loadFromPrefs('theme_mode');if(saved!=null){_themeMode=ThemeMode.values[savedasint];notifyListeners();}}Future<void>setThemeMode(ThemeModemode)async{_themeMode=mode;await_saveToPrefs('theme_mode',mode.index);notifyListeners();}}

鸿蒙兼容性

Material 3 的主题系统完全在 Flutter 框架层实现。ColorScheme.fromSeed的 HCT 算法和ThemeMode.system的亮暗检测都在 Flutter 引擎中完成。ThemeMode.system在鸿蒙上依赖@ohos/flutter_ohos引擎向 Flutter 报告系统亮暗模式。

如果鸿蒙设备上的系统亮暗模式检测有问题,可以通过MediaQuery.platformBrightnessOf(context)查看引擎返回的实际值,或在 Texture 中手动设置MediaQueryplatformBrightness

总结

Material 3 种子色主题系统让应用配色从"手动拼凑 12 个色值"简化为"选一个种子色":

  1. ColorScheme.fromSeed(seedColor: Color(0xFF4DB6AC)):一行代码生成 30+ 色调
  2. 亮色 + 暗色两个 ThemeDataBrightness.lightBrightness.dark控制色调层级
  3. ThemeMode.system:自动跟随系统亮暗设置
  4. HCT 色彩空间保证感知均匀度和无障碍对比度

完整项目代码见:todo_flutter_harmony

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询