SuperAPI AI 工具集

iphone-duo-react-native

前端与建站

查看项目

更新于 10-15 15:15

技能介绍

用途

本技能用于指导开发者将 React Native 或 Expo 应用适配 iPhone Duo——苹果首款折叠屏 iPhone。资料明确指出,React Native 没有折叠或铰链 API,没有 useDisplayFeatures,也没有铰链事件,JavaScript 无法感知设备是否折叠;截至撰写时,尚无任何 React Native 或 Expo 版本正式支持 iPhone Duo。因此适配工作分为两个层级。

主要能力

第一层:无需原生代码,当前即可使用

按边处理安全区域内边距

iPhone Duo 的安全区域是非对称的:iOS 会把控件移到屏幕一侧,因此左右内边距不同,具体哪一侧取决于折叠姿态以及应用占据分屏的哪一半。应使用 react-native-safe-area-context 的 useSafeAreaInsets(),它返回 { top, right, bottom, left } 四个独立数值,并在内边距变化时更新。

const insets = useSafeAreaInsets();
// each edge, independently
paddingLeft: insets.left,
paddingRight: insets.right,

需要避免三件事:

  • 使用 react-native 核心的 SafeAreaView——已废弃,且只正确处理过刘海屏场景。应使用上下文库的 hook 或其 SafeAreaView。
  • 对称计算——任何形如 width - insets.left * 2 的写法,在左右内边距不同时就是错误的,而在这台设备上这种情况占大多数。
  • 只读取一次内边距——它们会在应用运行期间变化,应通过 hook 在每次渲染时读取,而不是缓存。

如果在 React Native 0.81+ 且启用了 edge-to-edge,内容已经延伸到系统 UI 之下,正确的内边距处理就从装饰性变成了关键性。

每次渲染时响应尺寸变化

iPhone Duo 上窗口尺寸会不断变化:打开、合上、折叠、旋转、进入分屏。应使用 useWindowDimensions(),它是 hook,变化时会重新渲染;而 Dimensions.get('window') 返回的是快照,会悄悄过期。如果 Dimensions.get(...) 出现在模块作用域或常量中,在这台设备上就是 bug。对于组件级尺寸,onLayout 能给出实际测量框,比从窗口尺寸推导更可靠。

按宽度分支,而非按设备分支

iOS 以尺寸类思考:外屏是紧凑宽度,内屏是常规宽度。React Native 没有对应概念,因此应使用 useWindowDimensions() 的宽度断点。不要基于 Platform.OS、react-native-device-info 的设备型号或方向来分支。内屏不遵循 supported orientations,方向提供的信息比想象中少。

为内屏提供真正的布局

把手机布局拉伸到 7.6 英寸会显得未完成。低成本的做法是在宽断点以上使用双栏或主从布局;如果使用 React Navigation,宽屏用抽屉或侧栏式导航器,窄屏用标签页。

第二层:需要原生模块

真正 iPhone Duo 特有的功能需要从 Swift 桥接。按以下顺序值得做:

原生 API(iOS 27.1) 为何暴露给 JS
UIView 上的 reservedRegions(kind:) 让触摸目标避开折叠处和屏下摄像头
UIHingeInteraction 连续铰链角度,用于特效
traitCollection 尺寸类 iOS 实际使用的信号,替代断点猜测

模块形态

编写 TurboModule(新架构)或旧式原生模块,对任何连续数据使用 NativeEventEmitter。铰链角度是实时流——应以事件推送,不要让 JS 轮询。

从 React 内容挂载的视图查询保留区域,因为这些 API 依附于 UIView,区域是相对于某个视图报告的。将区域以普通对象({ x, y, width, height, kind, active })发出,让 JS 能直接据此布局。

严格防护。同一个 JS bundle 会在所有 iPhone 上运行,因此模块在非折叠设备以及低于 iOS 27.1 的系统上必须返回“无区域、无铰链”,而不是抛错。在 Swift 中做可用性检查,绝不假设。

如果在 Expo 中,这意味着配置插件加本地原生模块——无法在 Expo Go 中运行,需要开发构建。

然后接入第一层

一旦区域到达 JS,它们只是现有布局中的数字。围绕分隔区域定位的绝对定位 View 可让控件避开折叠处;从遮挡区域推导的 marginRight 可让内容避开摄像头。

使用方式

按顺序执行:

  1. 把所有 Dimensions.get() 换成 useWindowDimensions()。
  2. 把核心 SafeAreaView 换成 useSafeAreaInsets(),并审查每个内边距表达式是否有对称计算。
  3. 用宽度断点替换平台/方向分支。
  4. 添加宽布局路径,让内屏物尽其用。
  5. 只有在此之后才编写原生模块,且仅当折叠感知确实能改善应用时才做。

第 1–4 步是普通 React Native 工作,在平板和可折叠 Android 上也有收益。第 5 步是唯一 iPhone Duo 特有的部分,需要 Xcode 27.1 模拟器来测试。

适用场景

适用于正在维护 React Native 或 Expo 应用、需要为 iPhone Duo 折叠屏设备做适配的开发者。第一层方案对平板和可折叠 Android 同样有益。

限制

  • React Native 和 Expo 目前均无正式 iPhone Duo 支持,也无折叠或铰链 API。
  • 第二层原生模块需要 Xcode 27.1 模拟器测试,Expo 项目无法在 Expo Go 中运行。
  • 原生 API 需要 iOS 27.1 及以上,低版本和非折叠设备必须做降级处理。
  • 资料未提供具体收费、价格或平台信息。