Flutter 在 OpenHarmony 上跑起来已经不是新闻了,但真正把某个业务功能做到位、做到能上线,又是一码事。这段时间我正好在搞一个基于 Flutter 的 OpenHarmony 应用,里面有个高频需求——全屏弹窗,用来做登录引导、活动弹窗、视频播放前的广告位。一开始我以为这玩意跟 Android 上一样,直接 showDialog 塞个全屏参数就行,结果真上手才发现,坑比想象中多。
这篇博文就把我在 OpenHarmony 上实现 Flutter 全屏弹窗的完整过程写出来,包括方案选型、环境准备、核心实现、问题排查和性能调优,适合已经在 OpenHarmony 上跑过 Flutter Demo、准备认真做业务的开发者。如果你是刚接触 Flutter 和 OpenHarmony 的小白,也可以照着走一遍,代码和思路我都会展开讲。
1. 全屏弹窗的需求拆解与方案选型
1.1 这个需求背后到底在解决什么问题
先说业务场景。我做的是一个工具类应用,OpenHarmony 端的用户量虽然不大,但留存和活跃指标一直有要求。产品那边提了一个需求:用户冷启动之后,要弹一个全屏的活动页,展示新人礼包,点击按钮跳转落地页,点空白区域或右上角关闭按钮能退出。这个需求在 Android 上很成熟,但在 OpenHarmony 上就涉及到两个核心问题:一是 Flutter 侧的页面栈和原生侧的页面栈怎么协同,二是“全屏”这个视觉概念在两个渲染体系里怎么统一。
全屏弹窗的核心诉求有三个:
- 覆盖到底:从状态栏顶部到系统导航栏底部,不能露出原来的页面边缘,也不能有白边。
- 独立导航:弹窗内部的按钮跳转不能影响 Flutter 的主导航栈,关闭时必须能精确回到弹窗打开前的页面。
- 沉浸式体验:弹窗背景可以是半透明遮罩,也可以是完全不透明的运营页,后者对渲染性能和内存要求更高。
如果只做 Flutter 层级的弹窗,用 Dialog 的 insetPadding 调成零就能做到视觉全屏,但在 OpenHarmony 上,Flutter 的页面渲染是在一个原生容器里进行的,这个容器本身可能带着系统的安全区域边距。你不处理这一层,弹窗就会出现上下黑边,或者盖不住状态栏。
1.2 三条实现路线,我为什么最终选了这条
我在动手之前梳理了三种方案:
路线一:纯 Flutter 层实现,通过 showGeneralDialog 或者 showDialog 加自定义 Route 实现全屏效果。 这种做法实现成本最低,复用性最高,全屏弹窗本质上就是一个全屏路由页面,转场动画可以自己定义。但在 OpenHarmony 上,它会受限于 Flutter 容器所在的原生页面大小,如果原生层设置了安全区域,Flutter 的 MediaQuery 就会拿到不准确的尺寸,导致弹窗底部被导航栏挡住。
路线二:Flutter 调用 OpenHarmony 原生能力,用原生弹窗控件渲染。 这种做法性能和系统集成度最好,但开发工作量直接翻倍。你需要写端侧代码,还要维护 Flutter 和原生两套 UI 逻辑,运营活动页迭代频繁,这种方案没法满足快速出稿的需求,人力和时间成本都撑不住。
路线三:以 Flutter 为主,通过 PlatformView 嵌入原生视图,或者用 Overlay 叠加 Flutter 组件,通过通道控制 Flutter 页面和原生导航栈的协调。 这种做法兼顾了开发效率和原生能力,但需要在技术细节上处理很多边界情况,比如弹窗的层级、原生返回键的事件分发、页面生命周期同步等。
我最终选择的是路线三,但做了精简:弹窗 UI 全部用 Flutter 组件绘制,通过 Overlay 的方式插入到 Flutter 的顶层,同时通过 MethodChannel 让 OpenHarmony 原生侧调整安全区域和系统导航栏状态。这样日常改版只需要改 Dart 代码,原生层只做环境适配和系统级交互,是当前团队规模和节奏下性价比最高的方案。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备与工程搭建:先说清楚,再动手写代码
2.1 Flutter SDK 和 OpenHarmony SDK 的版本匹配
网上很多教程在讲 Flutter 安装,但到了 OpenHarmony 这边,版本匹配才是真正的分水岭。OpenHarmony 的 Flutter 适配分支由 OpenHarmony SIG 组维护,它跟上游 Flutter 的版本不完全同步。我用的是 OpenHarmony 的 ohos 分支,对应 Flutter 3.7.12 版本,这个组合在 rk3568 开发板上跑得最稳。
版本选定之后,环境变量也要单独配置。你本机可能装了标准 Flutter SDK,用于 Android 和 iOS 开发,同时还要装 OpenHarmony 的 Flutter SDK。两者不能共用同一套 flutter 命令,否则会出现依赖冲突。我是这样处理的:
bash复制# 标准 Flutter SDK 路径
export FLUTTER_STABLE_PATH=/opt/flutter
# OpenHarmony Flutter SDK 路径
export FLUTTER_OHOS_PATH=/opt/flutter_ohos
需要切换时,修改 PATH 环境变量即可。注意 OpenHarmony 分支的 Flutter SDK 下载下来之后,flutter doctor 可能显示部分检查不通过,这是正常的,因为它不需要检测 Android SDK 和 iOS 工具链。
提示:不要试图把两个 SDK 的 bin 目录同时加入 PATH,你一定会遇到版本混乱的问题,最后连 flutter pub get 都会报错。
2.2 创建支持 OpenHarmony 的 Flutter 工程
当 OpenHarmony 的 Flutter SDK 就绪之后,创建工程的命令跟标准 Flutter 工程略有不同。先进入 OpenHarmony SDK 路径下执行:
bash复制flutter create --org com.example --project-name fullscreen_dialog ohos_fullscreen
这里生成的工程结构里,ohos 目录是 OpenHarmony 的工程壳,需要用 DevEco Studio 打开并配置签名;lib 目录下的 Dart 代码是共享的。需要注意,OpenHarmony 的 Flutter 适配至少要求 API 9,建议直接用 API 10 或 API 11,不然部分系统能力接口会缺失。
工程创建之后,修改 ohos 工程里的 build-profile.json5,确保 signingConfigs 已经配置了你的开发者证书。没有签名的情况下,应用可以在模拟器上跑,但真机上装不了,推送和部分系统 API 也调不动。
