看了下官方的适配 Duo 设计指引,苹果的指南还真有点东西,看的头皮发麻,比如 Duo 下,外屏和内屏最好不能是两套 UI ,应用应该做到支持持续适应当前拥有的空间界面效果。

外屏、内屏、半折、Split View、横向摆放或者两个 App 并排,总体来说都是同一个问题:App 的窗口尺寸和可用区域正在变化,只要应用能够正确支持 resizing,然后支持使用系统导航和布局组件,Apple 认为大部分 App 都可以做到 Duo 适配。
嗯,如果用的不是系统布局和导航,确实会更多成本,这个对 Flutter 来说确实是一个小问题。

比如外屏的比例和传统 iPhone 有明显区别,又宽又矮,所以 Apple 把导航、Toolbar 和 Tab Bar 的一部分控制区域挪到了屏幕侧边,和外屏摄像头对齐,而且在内屏横向使用时,这套侧边控制结构还会继续保留,从外屏展开到内屏时,控件不会突然从侧边跳回顶部和底部:


Apple 在开发者 Tech Talk 中说过,Duo 内屏不会按照 App 声明的 supported interface orientations 来决定界面布局 ,也就是过去大量依靠 portrait、landscapeLeft 判断页面结构的代码大概率需要重新适配,布局需要通过 Size Class、Trait Collection 和真实窗口尺寸来处理。
而且 Apple 设计上就一直强调外屏和内屏最好保持同一个 App,只把信息层级展开,比如上面的邮件例子:
- 外屏显示一个主要信息层级,例如邮件列表或者当前邮件正文
- 展开以后,左侧显示邮件列表,右侧还是继续显示当前邮件正文,UI 没有突变进入另一个所谓的"平板模式",当前邮件、导航位置和应用状态都延续下来,不会有太强的突变,UI 是一个滑动放大的过程
这种变化对应的就是 SwiftUI 的 NavigationSplitView 和 UIKit 的 UISplitViewController, 苹果说了这些标准导航容器会随着 Compact / Regular 环境自动折叠和展开,而且能够自动处理 Duo 中央的 Reserved Region,另外 Sheets、popovers、context menus 和 alerts 同样会参与系统适配。

所以 Duo 这新增的核心布局概念叫 Reserved Region,也就是过去做 iOS UI 可能大多数人只考虑 Safe Area,以前只需要顶部有状态栏和 Dynamic Island,底部有 Home Indicator,这些内容都在 Safe Area 外面。
但是现在多了 Reserved Region,这部分表示屏幕里有不能按照普通连续内容区域处理的位置:
- 第一类是外屏前置摄像头区域,以你为它始终显示,同时 Live Activity 出现时还可能扩展成 Dynamic Island
- 第二类是内屏前置摄像头,它平时会被隐藏,但是摄像头启动后也会产生 Reserved Region
- 第三类就是中间的 Folding Region,设备完全展开时,内屏可以近似看成一个连续平面,但是开始折叠以后,屏幕中央弯曲区域逐渐不适合放置按钮、弹窗和关键内容,所以系统也会把中央区域描述成一个 Reserved Region

所以 Reserved Region 还可以分成了 division 和 occlusion 两类:
- 折叠区域属于 division,它会把一个连续容器划分成多个可用区域
- 摄像头这类东西更接近 occlusion,需要避免内容和硬件区域重叠
如果你是原生开发,那么实际上系统组件已经帮你处理了大部分工作,比如 Alert、Context Menu、Sheet 会自动避开折痕,Split View 会自动改变列宽和边距,标准导航容器也知道如何适应这些区域。
也就只有自定义 UI 才需要主动查询 Reserved Region, iOS 27.1 就加入了 SwiftUI
ReservedRegion和 UIKitUIViewReservedRegion相关能力。
另外关于折叠过程的变化,苹果建议是用"局部位移"的说法, Duo 适配比较理想的状态类似这样:
- 完全展开 30% 列表 + 70% 内容
- 开始折叠 45% 列表 | Folding Region | 55% 内容
这样信息架构不会发生变化,变化的只是空间分配。

苹果的说法是,在内屏上尽量考虑偶数列,中央出现 Folding Region 后,四列可以比较自然地形成左右各两列,三列可能经常会碰上"中间一列究竟放在哪边"的问题。
另外除了传统 Split View,Apple 提供了 Arrangement View,它主要管理 Primary View 和 Secondary View,然后根据窗口尺寸、屏幕方向和 Reserved Region 自动重新组织两块内容:

比如地图 App 很适合右边的 Overlay 模式,视频编辑器可能也可以用类似方式,当然 Arrangement View 负责的主要是 layout,不负责 navigation,所以
NavigationSplitView、Tab View 之类的导航结构需要放在 Arrangement 外部。
另外一个 Duo 最大的 UI 变化就是 Vertical Controls,也就是把导航、工具栏和 Tab 控制放到屏幕侧边:

苹果给 Duo 建立了一条共享的 vertical bar region,而且在分屏显示时,可能会出现左边的 bar 控制左边 App,右边的 bar 控制右边 App :

如果你用系统 Toolbar 基本能做到大部分时候自动适配,但是你如果是自绘 UI 的话就需要自己处理了,这里麻烦的是,分屏时两边还不一样,因为右边是有摄像头的。
官方对于 Toolbar 的顺序也很具体:
- Vertical Axis 顶部首先放 Back、Close 一类主要导航按钮
- 然后是 Done 等显著动作
- 其他 Toolbar Group 按原有关系排列
- 空间不足时,项目默认从下往上进入 Overflow,开发者可以通过
ToolbarItemVisibilityPriority或UIBarButtonItemVisibilityPriority调整保留优先级
然后还有个关键设定,那就是控件跟谁有关就应该靠近谁,比如这里区分 Mail 左右两个 Pane,右侧邮件正文相关的按钮可以进入最右侧 Vertical Toolbar,左侧邮件列表自己的按钮保持在留在列表上方:

最后,因为外屏的 Vertical Axis 长度有限,还要和状态信息、Dynamic Island 共用空间,所以 Toolbar 和 Tab Bar 不可能永远完整显示,这时候官方提供了两种方案:
- Tab Bar 完整保留,Toolbar 的部分操作进入 Overflow
- Toolbar 完整保留,Tab Bar 收缩成一个入口

苹果还要求尽量使用系统 Overflow Menu,如果 App 本来已经有一个"..."菜单,最好把可以溢出的 Toolbar Action 合并进去,避免页面上同时出现两个含义接近的省略号菜单。
最后
可以看出来,虽然只是多另一个 Duo 产品,但是对 UI 适配和交互其实多了很多东西,但是不适配也能用,就是会丑很多,相信苹果也是在后续开始强制 App 适配,所以怎么滴都是逃不掉的:
