当前位置: 首页 > news >正文

Flutter Dark Mode 在 OpenHarmony 系统中的适配实践

欢迎加入开源鸿蒙跨平台社区:
https://openharmonycrossplatform.csdn.net

Flutter Dark Mode 在 OpenHarmony 系统中的适配实践

前言

最近在做 Flutter for OpenHarmony 项目时,深色模式适配这块花的时间比我预想中要多。

一开始我以为:

Flutter 本身已经支持 ThemeMode 了,适配暗黑模式应该不复杂。

结果真正接入 OpenHarmony 真机之后,还是遇到了一堆细节问题。

包括:

  • 系统深色模式切换后页面不更新
  • 部分组件颜色异常
  • 状态栏颜色不统一
  • 页面切换时闪白
  • 图片资源不适配暗色主题

尤其是多个页面叠加后,颜色管理会越来越乱。

后面我重新整理了一套主题管理方案,整体体验才稳定下来。

这篇文章主要记录一下我这次在 OpenHarmony 项目里的 Dark Mode 适配过程。


一、为什么现在必须适配 Dark Mode

现在大部分系统都已经默认支持深色模式。

包括:

  • Android
  • iOS
  • OpenHarmony

如果应用完全不适配:

用户体验会比较割裂。

尤其晚上使用时:

亮白页面会特别突兀。


我项目里的实际场景

当前项目包括:

  • 首页
  • 商品列表
  • IM 聊天
  • 用户中心
  • WebView 页面

很多页面一开始都是直接写死颜色:

Container( color: Colors.white, )

结果系统切暗黑模式后:

页面直接“半黑半白”。


二、Flutter ThemeMode 基础接入

Flutter 本身已经提供了主题切换方案。


MaterialApp 配置

MaterialApp( theme: lightTheme, darkTheme: darkTheme, themeMode: ThemeMode.system, )

这里:

ThemeMode.system

表示:

跟随系统主题。


三、浅色主题与深色主题拆分

后面我把所有主题单独拆了。


light_theme.dart

final ThemeData lightTheme = ThemeData( brightness: Brightness.light, scaffoldBackgroundColor: Colors.white, appBarTheme: const AppBarTheme( backgroundColor: Colors.white, ), );

dark_theme.dart

final ThemeData darkTheme = ThemeData( brightness: Brightness.dark, scaffoldBackgroundColor: Colors.black, appBarTheme: const AppBarTheme( backgroundColor: Colors.black, ), );

这样后面维护会轻松很多。


四、不要直接写死颜色

这个是我这次适配里踩得最多的坑。


之前的代码

Text( "用户信息", style: TextStyle( color: Colors.black, ), )

暗黑模式下:

文字直接看不见。


后来的方案

统一改成:

Text( "用户信息", style: TextStyle( color: Theme.of(context) .colorScheme .onBackground, ), )

或者:

Theme.of(context).textTheme

统一从主题读取颜色。

后面适配会轻松很多。


五、OpenHarmony 上的一个实际问题

这个问题我在鸿蒙真机上复现得挺明显。


问题现象

系统已经切成暗黑模式。

但 Flutter 页面:

没有实时更新。

需要:

  • 重启应用
  • 或重新进入页面

主题才生效。


后来的处理方式

监听页面亮度变化。

WidgetsBindingObserver

监听:

didChangePlatformBrightness()
@override void didChangePlatformBrightness() { final brightness = WidgetsBinding.instance .platformDispatcher .platformBrightness; print(brightness); }

然后主动更新 ThemeMode。

这个在 OpenHarmony 上会稳定很多。


六、状态栏颜色适配

这个问题很多人容易忽略。


问题

页面已经切暗色。

但状态栏:

还是黑字。

结果顶部直接看不清。


解决方案

SystemChrome.setSystemUIOverlayStyle( const SystemUiOverlayStyle( statusBarColor: Colors.transparent, statusBarIconBrightness: Brightness.light, ), );

浅色模式:

Brightness.dark

深色模式:

Brightness.light

这个在 OpenHarmony 真机里效果挺明显。


七、图片资源适配

这个也是后面项目里很容易出问题的地方。


问题

深色模式下:

原本的黑色图标直接“消失”。

例如:

  • 返回按钮
  • tab 图标
  • 功能按钮

后来的方案

分别维护:

icon_dark.png icon_light.png

根据主题切换。

isDark ? "dark/icon.png" : "light/icon.png"

虽然麻烦一点。

但实际效果会好很多。


八、页面切换闪白问题

这个问题在 OpenHarmony 上我复现概率挺高。


问题现象

暗黑模式下:

页面 push/pop 时:

偶发白色闪屏。


原因

部分页面:

Scaffold

背景色没配置。

Flutter 默认会使用浅色背景。


解决方式

统一配置:

scaffoldBackgroundColor

同时:

页面不要直接:

Container(color: Colors.white)

这个优化后:

闪白问题减少很多。


九、Provider 管理主题状态

后面我把主题统一放到了 Provider。


ThemeProvider

class ThemeProvider extends ChangeNotifier { ThemeMode themeMode = ThemeMode.system; void changeTheme( ThemeMode mode) { themeMode = mode; notifyListeners(); } }

页面切换:

context .read<ThemeProvider>() .changeTheme( ThemeMode.dark, );

后面:

  • 设置页
  • 系统跟随
  • 手动切换

都方便很多。


十、缓存主题状态

这个我建议一定做。


为什么

否则:

每次重新打开 App。

主题都会恢复默认。


我的方案

使用:

shared_preferences

保存:

await prefs.setString( "theme", "dark", );

启动时恢复。

目前在 OpenHarmony 上没发现问题。


十一、实际效果

优化前:

问题表现
深色模式适配不完整
页面闪白存在
状态栏颜色异常
图标显示混乱

优化后:

项目效果
主题切换更稳定
页面体验更统一
暗黑适配基本完整
页面切换更自然

目前这套方案已经在项目里稳定用了挺长时间。


十二、总结

这次做 Flutter Dark Mode 在 OpenHarmony 下的适配,一个比较明显的感受是:

深色模式真正麻烦的地方:

其实不是 ThemeMode。

而是:

  • 全局颜色管理
  • 页面细节统一
  • 图标资源
  • 状态栏
  • 页面生命周期

尤其项目越来越大之后:

如果前期没有统一主题规范。

后面补 Dark Mode 会非常痛苦。

我现在项目里的原则基本是:

  • 不直接写死颜色
  • 所有颜色统一 Theme 管理
  • 图标区分明暗资源
  • 页面背景统一配置
  • 状态栏跟随主题变化

整体体验会稳定很多。

后面我还准备继续研究:

  • Material 3 动态主题
  • OpenHarmony 系统主题同步
  • Flutter 动态换肤
  • 多主题架构设计

希望这篇文章能给正在做 Flutter for OpenHarmony 开发的同学一点参考。

http://www.jsqmd.com/news/858576/

相关文章:

  • 探索AI编程工具的民主化:从技术壁垒到开源共享的技术演进之路
  • C#方法(方法的调用与定义与方法的参数)
  • 2026 年 5 月|企业培训无闭环、效率低?这 3 款平台让培管更简单 - 讲清楚了
  • 实测实锤!AI低代码造ERP,效率狂升600%,技术+避坑全拆解
  • AntiDupl.NET:智能图片去重工具的完整使用指南与实战方案
  • 四川志恒汇达:重竹地板塑木围栏 HUPC 幕墙优质供应商 - 深度智识库
  • vscode使用claude code接入deepseek教程
  • 终极密码学工具箱ToolsFx:30+编码转换与一键解码的完整解决方案
  • 机器标识重置技术:如何优雅地绕过Cursor的试用限制
  • Honey Select 2中文汉化补丁终极指南:一键安装完整中文体验
  • Onekey Steam清单下载器:5分钟学会专业游戏清单管理
  • 【自然语言处理2】分词
  • 黑苹果配置革命:OpCore-Simplify如何用10分钟解决3天的难题?
  • 拒绝移液误差背锅!进口助吸器性能与口碑TOP榜:哪些品牌评价好、长期用性价比更高? - 品牌推荐大师
  • 为内部知识库构建AI问答层,Taotoken多模型选型与接入实践
  • 2026洛阳手工米皮加盟与培训完全指南:从零经验到月入万元的轻资产创业路径 - 年度推荐企业名录
  • 太原启睿再生资源:太原专业的工地废料回收公司选哪家 - LYL仔仔
  • G-ratio Overload
  • 07 DeiT 论文精读:Training data-efficient image transformers distillation through attention
  • XZ9628输入电压2-24V 输出电压可调可达28V 内部4A限流 升压转换器芯片
  • 终极指南:如何在Mac上免费快速制作Windows启动盘?
  • 主流C语言开发环境(IDE)汇总与推荐
  • 视启未来[特殊字符]百度智能云:给大模型一双手,让AI真正触碰物理世界
  • 西安补习学校哪家好?2026家长口碑实测推荐靠谱机构 - 深度智识库
  • 领跑者!2026玻璃钢储罐厂家TOP5:以技术降本增效,以服务护航安全 - 速递信息
  • 2026西安公司注销代办哪家靠谱?异地|执照丢失|吊销注销一站式办理|宸悦财税 - 奔跑123
  • 2026年深圳藤校申请高端定制怎么选?留学中介哪家更靠谱更专业 - 品牌2025
  • OpenModScan:工业自动化领域的终极Modbus调试解决方案
  • Superpowers 角色体系:六种智能体协作详解
  • 协作机器人焊接厂家哪家强?六大优质工厂核心优势与案例全解析 - 深度智识库