首页
/ Impeccable 原生端适配实战:adapt 命令的 native 变体如何把"放大手机 UI"变成跨设备、跨平台的重构

Impeccable 原生端适配实战:adapt 命令的 native 变体如何把"放大手机 UI"变成跨设备、跨平台的重构

2026-09-04 18:17:40作者:柯茵沙

Impeccable 是一套为 AI 编程助手(Agent)提供设计能力的设计语言技能包,其中 adapt 命令负责把已有设计迁移到新的设备、屏幕或平台语境。本文聚焦其原生端参考手册 adapt.native.md(适配 iOS / Android / adaptive 项目),完整拆解它"评估挑战 → 选择策略 → 实现验证"的工作流,并结合仓库中的平台参考(ios.md / android.md)、命令路由规则与 context.mjs 脚本实现,说明这条 Playbook 是如何被技能系统自动选中和执行的。读完后你将掌握:原生适配的四类典型场景(手机→平板、横屏/折叠屏、iOS↔Android、Web→原生)的具体策略、可直接复用的平台惯用法对照表,以及"尺寸类驱动结构、硬件做真值验证"的落地原则。

adapt.native 手册在 Impeccable 技能中的定位

adapt 是 Impeccable 技能 Commands 表中的一条 Fix 类命令,官方描述为 "Adapt for different devices and screen sizes",并明确分成两套参考手册:Web 版 adapt.md 与原生版 adapt.native.md.agents/skills/impeccable/reference/ 下的文件是同一内容的分发包副本,见 adapt.native.md)。技能的路由规则写在 SKILL.src.md 中:

  • 无参数调用 $impeccable 时读取 routing.md 呈现上下文感知菜单,绝不自动执行命令;
  • 显式或可推断的命令(如"把这个 iOS 界面做成 iPad 版")则加载对应参考文件,且原生平台上加载 native 变体
  • adapt 命令头部声明了执行前必须补齐的上下文:目标平台/设备与使用场景> Additional context needed: target platforms/devices and usage contexts)。

手册开篇即给出整条 Playbook 的核心断言:

Adapt an existing native design (ios / android / adaptive) to a different context: another device class, orientation, platform, or origin. The trap is treating adaptation as scaling. The job is rethinking the experience for the new context, inside the platform conventions of ios.md / android.md.

即:适配的陷阱是把"适配"当成"缩放"(scaling)。真正的工作是为新语境重新思考体验,并且必须约束在目标平台的约定之内——这也是为什么手册要求在执行前,如果 Setup 阶段尚未读取过目标平台参考(ios.mdandroid.md),必须先读。

技能系统如何知道该走 native 分支

平台判定来自项目根目录 PRODUCT.md## Platform 字段,合法取值为 web / ios / android / adaptive(跨平台,同时面向两个原生端;写成 ios, android 两个目标也会被解析为 adaptive)。解析逻辑在 context.mjs 中,当字段值无法识别时会输出警告并把项目按 web 处理。随后 Setup 阶段的 context.mjs 会按平台加载对应的平台参考文件,核心实现是 loadNativePlatformReferences

function loadNativePlatformReferences(platform) {
  const names = platform === 'adaptive'
    ? ['ios', 'android']          // adaptive 项目两份平台参考都要读
    : platform === 'ios' || platform === 'android'
      ? [platform]
      : [];
  // ...读取 SKILL_REFERENCE_DIR 下对应的 <name>.md 并注入会话上下文
}

从源码结构看,adaptive 项目会同时注入 ios.mdandroid.md 两份平台规则,这解释了为什么跨平台应用(Flutter、React Native、Expo)做平台迁移时,Agent 已经同时持有两套平台的"规则书"。

还有一个容易被忽略的事实:原生项目不适用 Impeccable 的浏览器侧工具routing.md 明确指出 livedetect.mjs 是 web-only;context.mjsautomaticHookModeios / android / adaptive 平台直接返回 'none'(设计检测钩子不启用),appendDetectorFallback 也注释了 "The detector reads HTML and CSS, so native projects get nothing"。换句话说,原生端的质量把关不靠 HTML 规则引擎扫描,而是靠本文后面讲的平台 slop 测试 + 真机验证这条人工/Agent 复核路径。

第一步:评估适配挑战(Assess Adaptation Challenge)

手册把适配前的调研压缩成三个问题,分别回答"从哪里来、到哪里去、哪里会坏":

  1. Source context(源语境):它原本是为谁设计的、做了哪些假设?只面向手机?只面向竖屏?只用了某一个平台的惯用法?还是一套网站改过来的?
  2. Target context(目标语境):目标设备类(手机、平板、折叠屏)、屏幕方向、平台,以及使用姿态——是"单手持机在路上"还是"双手持握在固定场景"?
  3. What breaks(什么会坏):哪些导航放不进目标设备?哪些布局只会"被拉长"而不会"重新组织"?哪些手势或控件在目标平台上根本不存在?

这三问对应了原生适配最常见的三类失败:把 iOS 的 Tab bar 原样搬到 Android、把竖屏单列布局在横屏上直接拉伸、把 Web 的 hover 交互留在触屏上。评估阶段不写任何代码,它的产出是一张"断裂点清单",决定后续从哪几个策略入手。

四类适配策略

策略一:Phone → Tablet(手机 → iPad / 大屏)

手册的第一原则是 Restructure, don't stretch(重构结构,而不是拉伸布局)——"平板上的放大版手机 UI"是明确的失败模式。具体做法:

  • 用尺寸类切换结构:iOS 用 size classes、Android 用 window size classes,根据窗口尺寸类切换整体结构,而不是判断具体机型;
  • 导航形态随之改变:iOS 的 Tab bar 在 iPad 上保留或转为侧边栏(sidebar);Android 的 Navigation bar 在展开宽度(expanded width)下变为导航导轨(rail)或抽屉(drawer);
  • 用满宽度:手机上的单列表格/全屏 sheet,在平板上变成分栏(split view / master-detail,列表+详情并排)、多列网格;手机用 bottom sheet 的场景,平板上可以改为 popover;
  • 多任务是一种尺寸,不是边角情况:iPad Split View 与 Android 多窗口随时会把一个"手机宽度"的窗口塞给平板应用。以尺寸类驱动的布局天然同时覆盖"全窗平板"与"分屏手机宽度"两种形态,无需特判。

这一点与 android.md 的硬规则一致:"Never ship a phone bottom-bar untouched on a tablet"(绝不把手机底部导航栏原封不动地发到平板上)。

策略二:Orientation & Foldables(横屏与折叠屏)

  • 横屏要重构,不是裁剪:并排面板(side-by-side panes)、控件重新定位(repositioned controls);永远不做裁剪(clip)或加黑边(letterbox);只有当任务本身确实要求时才锁定屏幕方向。
  • 折叠屏(Android)以姿态和铰链为响应信号:通过 window size classes 感知设备处于折叠(folded)、展开(unfolded)还是支架(tabletop)形态。测试矩阵必须覆盖这三种状态。

策略三:Platform → Platform(iOS ↔ Android 互迁)

核心原则一句话:Translate idioms, never transplant(翻译惯用法,绝不移植控件)。手册给出了一张完整的 iOS ↔ Android 惯用法对照表,这是本手册信息密度最高的部分:

iOS Android
Tab bar Navigation bar / rail / drawer
边缘左滑返回、返回箭头(back chevron) 预测式返回手势(Predictive Back gesture)/ 返回按钮
Switch、分段控件、系统选择器 Material 开关、chips、Material 选择器
Action sheet Bottom sheet / Material dialog
SF Symbols、SF Pro、Dynamic Type Material Symbols、Roboto、sp 缩放
语义系统色、materials(材质) Material 颜色角色(color roles)、色调化 elevation(tonal elevation)
系统 push / sheet 转场 Container transform、shared-axis、fade-through

迁移的正确姿势是:用目标平台的词汇重建导航与控件,然后把品牌的表达层——配色意图(palette intent)、字体强调(type accent)、动势个性(motion personality)——通过目标平台的主题系统带过去。这与两份平台参考的立场完全一致:ios.md 说品牌通过 "tint、type、motion、content" 这层平台留给你的空间表达;android.md 说品牌通过 Material 的 theming(color roles、type scale、shape、motion)表达,且"穿着 Android 皮肤的 iOS 应用"(bottom-only 导航、无视系统返回手势的返回箭头、Cupertino 风格的开关和弹窗)是最典型的 Android slop。

策略四:Web → Native(把网站或 Web App 移植到原生)

原则是 Reconform, don't reflow(重新定型,而不是重新流式排版),做四组替换:

  1. Web 导航(顶栏、侧栏、面包屑)→ 平台的导航模型(iOS 的 Tab bar + 导航栈 / Android 的 Navigation bar + 顶层应用栏);
  2. HTML 形态的控件(div 按钮、自定义下拉)→ 平台控件(见上表);
  3. Hover 依赖的交互 → 触摸优先的交互(原生没有可靠的 hover);
  4. px 字号 → Dynamic Type(iOS)/ sp 单位(Android),让文本跟随系统字号设置。

移植完成后,整份目标平台参考就是验收标准:ios.md 的 "iOS slop test"(一个熟练 iPhone 用户会不会在不符合规范的控件上停顿?典型破绽是"从网站搬来的":自造导航栏、自定义返回手势、Web 形状的按钮、hover 依赖的交互)与 android.md 的 "Android slop test" 就是移植结果的及格线。

第二步:实现与验证(Implement & Verify)

手册给出三条实现约束和一条验证矩阵:

  1. 结构由尺寸类驱动,禁止机型判断——"Drive structure from size classes / window size classes, never from device-model checks"。按 iPad Pro 13" 之类机型分支的布局无法覆盖分屏、外接显示、未来新设备;尺寸类是平台提供的稳定抽象。
  2. 每种新形态都要尊重安全区与窗口内边距:刘海/灵动岛(notch)、折叠屏铰链(hinge)、状态栏、键盘(IME)都会吃掉屏幕边缘。对应到平台规则:ios.md 要求所有布局落在 safe-area insets 内、任何控件不得压在刘海/圆角之下;android.md 要求 edge-to-edge 模式下应用 status bar / navigation bar / display cutout / IME 四类 insets。
  3. 模拟器给广度,真机给真值:模拟器上跑广度(breadth),真机上要真值(truth)。最低验证矩阵是每个交付平台各一台手机 + 一台平板、两种方向、支持分屏的分屏形态;折叠屏再加折叠/展开/支架三态。

两份平台参考还把"真值验证"落实到了可执行命令上,可直接复制使用:

  • iOS(见 ios.md 的 "Verifying the build"):截图一律来自模拟器而非浏览器,构建运行后用

    xcrun simctl io booted screenshot <path>
    

    抓取(多台设备同时运行时用 xcrun simctl list devices booted 取目标 UDID 替换 booted,显示名可能撞车,UDID 不会);Dark Mode 与 Dynamic Type 必须进验证路径,xcrun simctl ui booted appearance dark 切换外观,再在大号 Dynamic Type 下检查固定布局会隐藏的截断问题。

  • Android(见 android.md 的 "Verifying the build"):

    adb exec-out screencap -p > <path>          # 多设备时用 adb -s <serial> 指定
    adb shell cmd uimode night yes             # 切换深色主题
    adb shell settings put system font_scale 1.3   # 放大字号(完事后改回 1.0)
    

    字号放大一步能抓出固定布局隐藏的标签截断。

  • 两份参考都以同一句话收尾:Simulators/Emulators give breadth; posture, gestures, and performance need hardware(模拟器给广度;姿态、手势、性能要靠硬件),并要求在产出证据时说明是哪类设备生成的。

验证通过、"适配在每种语境下都显得原生"之后,手册的交棒指令是:hand off to $impeccable polish for the final pass(交给 polish 命令 做上线前最后一轮质量收尾)。注意分工:adapt 负责"语境正确性"(结构、导航、平台惯用法),polish 负责"最后打磨",两者不是同一个环节。

五条 NEVER:原生适配的绝对禁令

手册结尾的禁令列表(原文语义完整保留):

  1. 不要把拉伸的手机布局发到平板上(Ship a stretched phone layout on a tablet);
  2. 不要把一个平台的控件或导航移植到另一个平台(Port one platform's controls or navigation onto the other);
  3. 不要在小尺寸设备上隐藏核心功能——如果功能重要,就让它可用(if it matters, make it work);
  4. 不要靠锁定屏幕方向来逃避布局 bug(Lock orientation to dodge a layout bug);
  5. 不要只信模拟器——姿态、手势和性能需要真机验证(posture, gestures, and performance need hardware)。

这五条禁令与评估阶段的"What breaks"三问、策略阶段的"never transplant"形成闭环:评估找断裂点,策略防惯性移植,禁令兜底防捷径。

延伸阅读:手册与仓库源码的对应关系

环节 文档/代码位置
native 适配 Playbook(本文主体) adapt.native.md(分发副本 adapt.native.md
Web 版 adapt(对照) adapt.md
iOS 平台规则(slop test、安全区、Dynamic Type、simctl 验证命令) ios.md
Android 平台规则(Material 3、48dp 目标、adb 验证命令) android.md
命令表与 native 变体路由 SKILL.src.md
无参数时的上下文菜单与 web-only 工具边界 routing.md
平台解析(## Platform 字段、adaptive 判定) context.mjs
按平台加载平台参考(adaptive 加载双端) context.mjs
原生平台禁用设计检测钩子 / 手动检测回退 context.mjscontext.mjs

适用前提与限制:本手册面向的是 PRODUCT.md## Platform 声明为 ios / android / adaptive 的原生项目(SwiftUI/UIKit/Compose/Views/React Native/Expo/Flutter 等),不涉及 Web 响应式适配(那是 adapt.md 的范围);其验证环节依赖 Xcode 模拟器与 adb 环境,xcrun simctladb 命令分别要求 macOS 开发环境与已连接的 Android 设备/模拟器。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
904
1.82 K
docsdocs
暂无描述
Markdown
889
5.78 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
527
590
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.52 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.33 K
1.45 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384
flutter_flutterflutter_flutter
本仓库是 Flutter SDK 与 Flutter Engine 的 OpenHarmony 适配版本,由 CPF-Flutter 团队维护。开发者可使用熟悉的 Flutter 技术栈开发 OpenHarmony 应用,3.35.7 及以后的适配版本可基于本仓库源码构建支持 OpenHarmony 的 Flutter Engine。
Dart
1.17 K
341