近几年做跨端开发,Flutter 是绕不开的一个技术栈;而 OpenHarmony 这边,随着生态逐步成熟,也有越来越多团队开始尝试用它跑业务级 App。这两个东西放在一起,最有意思的不是“能不能跑通”,而是业务落地时,工程化怎么做、UI 怎么设计才能既保证体验、又不会把自己折腾死。
这篇文章想聊的,就是一个基于 Flutter × OpenHarmony 的跨端车辆维修管理系统。系统本身不算复杂,核心是给维修厂、连锁门店提供一个既能跑在 Android/iOS,又能跑在鸿蒙设备上的管理工具。但我不会去铺开讲整个系统,而是聚焦在欢迎区域(启动欢迎页/首页头部区域)的 UI 设计与工程化实现上。原因很简单:跨端项目里,UI 层是踩坑最密集、也最能体现工程化水平的地方;而欢迎区域又是用户打开 App 后看到的第一眼,能不能在 OpenHarmony 设备上稳定、流畅地渲染出来,直接决定这个跨端方案到底可不可用。
如果你正在做 Flutter 跨端项目,或者准备把 Flutter 业务迁到 OpenHarmony,又或者只是好奇鸿蒙设备上跑 Flutter UI 到底什么体验,这篇文章应该能给你一些参考。我会把设计思路、代码结构、主题适配、动效实现、遇到的实际问题,包括 RK3568 这类设备上的表现,都拿出来说说。
1. 为什么选 Flutter × OpenHarmony:跨端方案的取舍逻辑
先交代一下背景。这个车辆维修管理系统,最初的形态是纯 Android 原生应用,后续因为门店里开始出现鸿蒙设备,而且业务方要求 iOS 版本也要尽快跟上,我们才认真考虑了跨端方案。选型的时候,摆在桌面上的选项主要有三个:React Native、自研容器、Flutter。
1.1 多端复用是硬需求,但原生体验不能丢
车辆维修管理这个场景,看起来只是“表单 + 列表 + 详情页”,但实际用起来,对交互流畅度的要求并不低。维修工单列表要频繁刷新,车辆检测报告要支持图片缩放和标注,还有大量需要键盘输入的场景。RN 那套桥接方案在复杂列表和动画上,性能调优成本会明显偏高,尤其是遇到第三方原生控件和 Flutter 混编的情况,跨端一致性很难保障。
Flutter 的优势在于,UI 层完全自绘,不依赖系统原生控件。也就是说,同一套 UI 代码,在 Android、iOS、OpenHarmony 上渲染出来的效果,理论上是一致的。这正好符合我们这个项目“一套设计、多端一致”的核心诉求。再加上 OpenHarmony 的 Flutter 适配已经能跑通基础渲染,选 Flutter 算是兼顾了体验和多端复用。
1.2 为什么特定盯着 OpenHarmony 适配
很多团队做跨端,只考虑 Android 和 iOS 就结束了。但 OpenHarmony 这个分支,在这个项目里不是“锦上添花”,而是“必须支持”。原因有两层:一是门店端确实有鸿蒙设备在部署,二是 OpenHarmony 的生态虽然还在建设中,但它在中低端硬件(比如工位平板)上的性能表现,反而比预期好。我们实际跑下来,RK3568 那块板子上的 Flutter 应用,帧率稳定性意外地不错,只是设备树选择、硬件编码能力这些底层问题需要额外处理。
所以,这个项目的价值标签不是“能用 Flutter 跑鸿蒙”,而是在 OpenHarmony 设备上,用 Flutter 实现了一套可交付的业务系统,并且 UI 设计上做了充分的工程化约束。接下来聊的欢迎区域,就是这个流程里的敲门砖。
1.3 Flutter 版本与鸿蒙 SDK 的配套关系
说句实在话,OpenHarmony 的 Flutter 适配,版本对齐是个很麻烦的事。官方 flutter_flutter 仓库的 OpenHarmony 分支,和社区维护的版本,往往相差几个 RC 版本。我们这个项目锁定的是 Flutter 3.22 配套的 OpenHarmony SDK 版本,在我写这篇文章的时候,这个组合算是相对稳定的。
提示:如果你准备自己搭环境,先别急着用最新的 Flutter master 分支。OpenHarmony 侧 Flutter 引擎的合入速度通常比 Flutter 主线慢一个版本,用太新的 Flutter 版本,经常会在编译期就报 API 不匹配。建议先确认 OpenHarmony SDK 里自带的 Flutter 引擎版本,再反推 Flutter 框架版本。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 欢迎区域的设计拆解:它到底承载了什么
所谓“欢迎区域”,在不同项目里指代的东西不一样。有些项目是单独的 Splash 启动页;有些项目是首页顶部的品牌展示区。我们这个系统里,两者都做了,并且设计上是统一的——启动页短暂展示品牌主视觉,进入首页后,顶部区域延续同样的设计语言,形成视觉连续性。这一块 UI 虽然看起来不复杂,但它是整个 App 的“门面”,在设计上我们特意对着四个维度做了拆解。
2.1 品牌区设计:不只是一张 Logo
欢迎区域的第一层,是品牌区。考虑到维修管理系统的使用场景——维修技师手上可能戴着手套,光线环境不稳定,屏幕可能沾着油污——品牌区不能走“小而美”的路线。Logo 要够大,主色调要够重,信息要够少。
我们最终定下的方案是:深色渐变背景(从深灰蓝到深灰绿),中间放一个白色系 Logo 图形,下方用大字重输出系统名称“车辆维修管理系统”,再往下是版本号和设备联网状态。这个布局看起来简单,但每一条都是有原因的:
- 深色渐变背景:在工位强光环境下,深色背景能降低屏幕整体亮度的刺眼感;渐变又能给纯深色增加一点层次,不显得死板。
- 大字重系统名称:很多管理员是远距离扫一眼确认“是不是进对系统了”,字体太小识别度低。
- 版本号和联网状态:这是给实施人员和运维看的。跨端项目里,版本不一致是最常见的排查起点,把版本直接放在欢迎区域首屏,能省掉大量“你的版本是多少”的沟通成本。
2.2 功能入口与状态速览:把高频操作前置
欢迎区域不只是“好看”,它还得“有用”。我们在这块区域里放了两组东西:一组是高频功能入口(接车、开单、查工单),另一组是当日核心数据速览(待接车辆数、维修中工单数、今日完工数)。这些信息放在欢迎区域,不是设计上拍脑袋的决定,而是业务调研的结论——门店主管打开 App 后,最关心的永远只有四件事:现在有几台车在等、有几台在修、今天做完了几台、有没有异常工单。
这个区域用了一个横向滑动的卡片式布局(Carousel),每张卡片承载一个数据指标。卡片背景用了和品牌区呼应的渐变色调,但明度更高,和背景拉开层次。功能入口则做了一个 2×2 的宫格,放在卡片区下方,确保拇指热区能覆盖到。
2.3 动效与交互相:克制是关键
跨端项目里,动效是最容易“翻车”的地方。动画在 Android 上运行流畅,到了 OpenHarmony 的低端设备上可能掉帧;动画写得太重,列表滑动时还会引发连锁的卡顿问题。所以,欢迎区域的动效我们定了一个原则:能不用动画就不用动画,必须用动画时,只做透明度渐变和位置轻微偏移,绝不上物理模拟类动画。
实际落地的动效只有三个:
- 启动页 Logo 出现时,做了 0.6 秒的透明度渐变。
- 首页欢迎区域加载完成时,数据卡片从 12 像素偏移位逐渐复位,同时透明度从 0 变到 1。
- 下拉刷新时,欢迎区域整体做一个轻微的缩放反馈。
这三个动效都不超过 600 毫秒,不叠加,不循环。目的只是让界面切换看起来“不愣”,而不是追求视觉炫技。
2.4 主题颜色设计:从品牌色到 Flutter ThemeData
最后,整个欢迎区域的颜色体系,收敛成了一个完整的主题配置。我们定义了一套以“维修蓝 + 警示橙”为核心的品牌色板:
- 主色:#2B5C8A(维修蓝),用于主要按钮、强调文字、选中状态。
- 辅助色:#F5A623(警示橙),用于维修中、待处理等状态色。
- 背景色:#1A2733(深色背景)、#F5F7FA(浅色背景)。
- 文字色:#FFFFFF、#8A94A6、#3D4757,分别对应标题、二级文字、正文。
这套色板在后面实现 UI 时,会通过 Flutter 的 ThemeData 统一注入,所有页面直接从 Theme 里取色,不写死色值。这也是跨端项目里比较重要的工程化约束——颜色、字号、间距一旦在业务代码里写死,后续做深色模式、做多端适配时,就是一场灾难。
