CMP 共享 UI 开发指导
项目约定,自 2026-10-26 起适用于所有 UI 的后续演进。
目标
Android 和桌面优先使用同一套 Compose Multiplatform 呈现。Windows 与 macOS 使用同一个 desktop-app,共同消费共享组件。修复共享界面时,让所有消费端在重新构建后获得同一份修改。
共享覆盖页面结构、组件、状态模型、状态派生、交互规则和文案语义。代码放在共享目录但只有一个端 使用,或者两个页面仅使用同一批基础控件,都不足以证明整个页面已共享。
当前仓库是渐进迁移状态:core-ui 已共享部分界面,但仍有 Android 页面与桌面页面分别实现。 这些存量实现是迁移对象,不作为新页面继续分叉的模板。
放置边界
| 内容 | 默认位置 |
|---|---|
| Compose 页面、列表、卡片、标签栏、搜索与筛选呈现 | core-ui/src/commonMain |
| 跨端业务规则、排序、过滤、状态合并等纯逻辑 | 对应的 core-domain、core-source 或现有共享功能模块 |
| Android 导航、Activity、Hilt 装配、权限、系统文件选择 | app 或相应 androidMain |
| 桌面入口、窗口、文件选择、运行时与服务装配 | 现有桌面模块 |
| WebView、原生播放、安装更新等系统能力 | 相应平台适配器,通过接口或回调注入 |
共享呈现消费明确的状态和事件回调,保持对 Activity、Hilt、Swing、java.io.File、平台资源 ID 和平台运行时的隔离。已有 Android 页面若绑定这些对象,先拆出所需的呈现边界,而非重写桌面版本。 系统差异可使用接口、回调或适合该边界的 expect/actual,无需为每个差异新增框架。
共享文案优先使用项目现有的 UiStrings/uiString 与 Android 资源目录。平台说明使用平台侧文案, 避免把 Windows 的运行时术语带入所有平台的共用流程。
实施顺序
现有页面的盘点、优先级与分批验收见 CMP UI 收敛计划。执行具体批次前复核其工作树快照与源码依据。
- 查现有实现。 定位 Android 页面、桌面对应页面和
core-ui组件,记录状态来源、操作及平台依赖。 - 确定最小共享边界。 优先提取真实页面或具有完整交互语义的组件;仅因文件太大而拆分,不能解决重复实现。
- 提取并接回 Android。 把可共享呈现放入
commonMain,让原 Android 页面调用它,保持既有行为。 - 接入桌面。 桌面提供状态与系统操作;页面布局和相同操作继续调用共享实现。移除本次被替换的重复呈现。
- 验证消费端。 编译受影响的 Android 和桌面目标;检查共享交互与各端适配,记录实际运行过的平台。
修改存量页面时按当前功能范围逐步迁移,无需一次重写整应用。尚未收敛的部分应明确记录,后续继续 迁移;不以“以后会共享”为理由再新增一套同功能页面。
合理的平台差异
- 手机单栏、平板或桌面分栏,优先通过窗口约束与共享自适应布局表达。
- 触摸、鼠标、键盘和遥控器操作,接入同一状态与事件,保持可访问性和操作结果一致。
- 文件选择、权限、系统菜单、窗口、浏览器和原生播放保留平台实现,共享页面通过能力与回调消费。
- 平台暂不支持的能力由宿主明确声明,共享页面提供合适的可用状态与说明。
平台实现的差异应有具体的系统 API、能力或交互依据。单纯为了在桌面上运行,不能成为复制一套页面、 状态机或业务规则的依据。实现中把系统判断集中在能力边界,页面消费能力而非散布操作系统分支。
当前 iOS 使用原生 UI,core-ui 尚未配置 iOS 目标;本规则要求所有 UI 改动先评估共享, 不代表现有 SwiftUI 页面已经能直接消费 CMP。iOS 继续共享适用的业务与数据模型,UI 目标迁移需要 在相应任务中明确处理,而不是在普通页面修复中顺带重写。
完成标准
- 能指出共享实现的具体位置,以及 Android/桌面各自的调用入口。
- 共同的页面结构和交互修改进入共享实现;平台侧保留的部分有明确职责。
- 保留或验证搜索、筛选、选择、展开、安装、删除确认及状态恢复等本次涉及的行为。
- UI 改动检查宽窄窗口、滚动和输入方式;提供实际截图或交互测试结果。
- 列出编译、测试和实际运行的平台。Mac 验证通过不等于 Windows 系统适配已回归。
- 描述共享范围时区分组件共享、页面共享与功能共享,不把局部提取宣称为全应用共享。
项目结构依据:Kotlin Multiplatform 官方建议。