为 iPhone Duo 设计
概述
来源:Apple 人机界面指南,“Designing for iPhone Duo”(新页面,2026 年 9 月 9 日)。 https://developer.apple.com/design/human-interface-guidelines/designing-for-iphone-duo
核心原则:一个应用在两块屏幕和多种姿态间流畅调整大小。不要为每种姿态设计布局;使用尺寸类别(紧凑宽度 = 外屏,常规宽度 = 内屏),让标准系统组件进行适配。所有常规 iOS HIG 仍然适用。
当需要确切的措辞或特定规则的开发者 API 时,请获取上述页面。
硬件概述(一段话)
外屏(闭合时使用):比其他 iPhone 更宽且更短,摄像头固定在角落且始终可见。内屏(打开时使用):摄像头隐藏在屏幕下方,激活时才可见。中央铰链支持书本式、平铺式和边缘站立式姿态。工具栏、标签栏、状态栏和灵动岛位于 侧面(垂直轴),内屏竖屏时除外。
快速检查清单
布局
- 构建为可调整大小:尺寸类别、布局边距、安全区域插页。无固定宽度,不依赖于某一屏幕。
- 在两块屏幕和每种姿态下保持相同功能和状态。内屏可增加一级层次结构(邮件:闭合时为列表或消息,打开时并排显示)。
- 尊重保留区域:外屏摄像头(始终,扩展为灵动岛)、内屏摄像头(仅激活时)、折叠区域(仅部分打开时)。对自定义组件使用
ReservedRegion(SwiftUI) /UIView.ReservedRegion(UIKit)。 - 折叠时:优先选择自适应容器(分屏视图均衡窗格宽度),使用偶数列的网格,进行小调整,避免剧烈重新排列。
- 分屏视图:在内屏扩展,在外屏折叠为一个窗格,自动进行。
- 排列视图(
ArrangementView/UIArrangementViewController):两个视图,主视图 + 次视图。拆分(并排或堆叠,来自 HStack/VStack 式布局)或 覆盖(分层,来自 ZStack 式布局)。导航容器保持在其外部。
垂直控件
- 保持系统的侧边放置;通常不要覆盖它。
- 内容区域不对称:使用安全区域,以便侧边控件(包括分屏视图中其他应用的控件)永远不会覆盖内容。控件在 RTL 语言中保持在同一侧。
- 工具栏顺序,从上到下:主导航(返回、关闭),然后是突出操作(完成),其余组保持原样。
- 溢出默认从下到上;设置可见性优先级(
ToolbarItemVisibilityPriority/UIBarButtonItemVisibilityPriority),以便常用操作(撰写、新建备忘录)和带标记的项目保持可见。 - 使用
ToolbarItemGroup/UIBarButtonItemGroup对项目进行分组;切勿添加手动固定间距。 - 每个非文本工具栏项目同时包含标题和符号。尽量减少纯文本按钮(它们会留在水平条中)。
- 空间紧张时:导航聚焦视图将工具栏压缩到溢出(默认);任务聚焦视图则最小化标签栏(
ToolbarVerticalCompressionBehavior/UIVerticalBarCompressionBehavior)。 - 使用系统溢出菜单;省略号仅用于溢出。
- 属于非尾随窗格的控件保持在该窗格旁边(邮件列表控件保持在列表上方)。
- 沉浸式、非滚动的 UI 如果未与灵动岛或状态栏冲突,可以全宽度显示(计算器可设为 5 列 x 4 行)。
游戏
- 在每种姿态下可玩。锁定方向可以,但要填满屏幕。保持文本和控件大小一致。优先改变宽高比而非添加信箱/邮筒;如果不可避免,使用艺术作品填充空白。
来自 Apple 技术讲座
HIG 页面未详细说明的三场 Duo 技术讲座细节(111466 Design for iPhone Duo、111462 Raise the bar with iPhone Duo、111463 Strike a pose with adaptive layouts)。
需要设计的系统行为
- 外屏:控件位于 右侧,方便右手拇指触及。灵动岛随着 Live Activities 到达而垂直扩展,并与应用栏共享侧边区域。空间不足时,应用项目自动折叠到溢出中。
- 部分折叠(书本式):文本、图像和交互元素移离弯曲区域。竖屏折叠时,交互元素移至下半部分。
- 分屏多任务:使用主屏幕手势将应用拖到一侧,实现 50/50 均等分割。每个应用的控件位于其外边缘。
- 画中画可固定到顶部;下方的应用垂直调整大小,折叠时视频填满一半屏幕。
- 表单:在外屏上,表单工具栏变为垂直。在内屏上,表单居中,带有水平条。折叠时,表单滑离折叠处。使用
preferredPlacement,左侧放置的表单没有垂直条,右侧放置的表单则有一个。 - 内置的折叠回避(表单、警告、菜单、工具栏按钮等)将交互元素移离折痕。可滚动内容无需回避折叠。
选择使用垂直条
- 使用最新 SDK 重新构建。
- 使用导航容器拥有的栏:SwiftUI 中
NavigationStack、NavigationSplitView或TabView上的.toolbar;UIKit 中设置在UINavigationController/UITabBarController内视图控制器上的项。自定义的UIToolbar/UINavigationBar/UITabBar内容 不会 被移动。
- 只有显示边缘的容器才变为垂直。在分屏视图中,只有详情列如此;检查器不会获得自己的垂直条。
- 映射:顶部工具栏项目转到条带的顶部,底部项目到底部,标签栏保持底部对齐。灵活间隔器高度为零;固定间隔器保持其大小。
- 返回/关闭:使用导航控制器自动实现。自定义返回/关闭使用
.cancellationAction(SwiftUI) 或带有leftItemSupplementsBackButton = false的前导项 (UIKit)。突出操作使用topBarPinnedTrailing(SwiftUI) 或pinnedTrailingGroup(UIKit)。
哪些变为垂直,哪些保持水平
- 垂直条具有固定宽度和灵活高度,因此适合仅符号项目。带图标的项目变为垂直;仅文本项目(编辑、分段控件、宽文本按钮)保持在水平导航栏中。
- 使用新的 AxisBehavior API 覆盖:对在符号和文本之间变化的项目(自定义选择;系统编辑按钮自行处理)使用仅水平,对具有垂直形式的自定义视图(例如指南针)使用垂直首选。
- 使用徽章(iOS 26 徽章 API)将文本和符号项目转换为仅符号项目,例如收件箱计数。如果文本携带真实信息(购物车总额),则保留文本。
- 键盘附件栏保持附着在键盘上。
- 自定义视图:适配固定宽度或提供垂直布局。读取
toolbarVerticalEdge(环境值或特性),当栏不能垂直时为 nil。 - 垂直条默认 没有滚动边缘效果。仅在“降低透明度”开启时获得背景,因此自定义内容必须在两种情况下都清晰可读。
- 选择退出(单页、底部重应用如计算器,或仅有关闭按钮的表单),使用
toolbarVerticalBehavior/preferredVerticalBarBehavior。没有垂直条的表单刚好停在摄像头之前。 - 按视图压缩:
toolbarCompressionBehavior。可见性优先级可为高、低或自定义;先按组设置,再按项目设置。
布局模式
- 外屏:大多数内容需要偏移以避免被控件遮挡,对齐到水平安全区域插页可自动实现这一点。仅对沉浸式、非滚动 UI 且没有交互元素位于栏下的情况使用全屏居中。混合方法是全宽度背景搭配内嵌滚动内容,将所有交互元素保持在内嵌区域内。
- 内屏,避免只是一个拉伸的手机应用:使用分屏视图、宽时变为 2 列的堆叠布局(音乐),或者对于信息密集型应用,将标签栏显示为侧边栏(健康)。
- 可选的桌面(笔记本电脑)姿态布局:媒体在上方,控件在稳定的下半部分。必须保持每个控件和相同的层次结构。
- 位移:将元素移出保留区域,进入适合其用途的区域。选择范围:如果元素独立则单独移动,相关元素一起移动,不要将元素移离其来源太远。在书本姿态下,警告移至尾随侧,靠近闭合时它们将重新出现的位置。在桌面姿态下,可瞥视内容放在顶部,可点击控件放在底部。搜索保持在所搜索的视图上方。对于网格,保持外边距,在铰链处加宽间距(健身)。
- 系统分屏视图在折叠时均等为 50/50(提醒事项)。
保留区域 API
- SwiftUI:
GeometryProxy上的reservedRegion(来自GeometryReader或onGeometryChange)。UIKit:UIView上的reservedRegion。使用.frame进行布局。 - 有两种类型。一个 分割 区域(折叠)仅在折叠时激活,平铺时宽度为零。一个 遮挡 区域(内屏 FaceTime 摄像头)仅在摄像头开启时激活。
- 默认返回活动区域;使用
includeInactive进行预先规划(例如,只要存在分割区域就选择偶数列数)。 - 对于摄像头中心的应用,保持关键内容和控件远离内屏摄像头。
- 折叠状态作为交互输入的内容在讲座 Leverage multiple displays and scenes on iPhone Duo 中涵盖,本技能未包含。
排列视图(iOS 27.1)
- SwiftUI:
ArrangementView(primary, secondary)放在NavigationStack内,使用.arrangementViewStyle(.split)(默认)或.overlay样式。使用.split.axes(...)限制拆分方向;如果无法沿主轴拆分,则仅显示主视图。 - UIKit:
UIArrangementViewController作为导航控制器的根,使用UISplitArrangement进行updateArrangement。 - 覆盖:平铺时堆叠,折叠时并排。读取
overlayArrangementZIndex(SwiftUI) 或state(for:)然后.zIndex(UIKit) 以在折叠和展开的次视图之间切换。 - 选择:遵循现有模式(HStack/VStack 变为拆分,ZStack 变为覆盖)。否则对于前景/背景关系使用 覆盖,部分遮挡滚动内容也可以(辅助功能阅读器);对于主/详情且两个视图都不能被遮挡的情况使用 拆分(播客文稿)。
- 不要在 ArrangementView 内放置导航容器,也不要在
List/ScrollView内放置 ArrangementView。
就绪审计(来自讲座)
- 使用最新 SDK 重新构建。
- 审计栏:系统容器、项目顺序、带标题的符号。
- 使自定义项目准备好垂直化。
- 设置溢出优先级。
- 审计居中布局:每个布局应变为 2 列、位移,还是使用 ArrangementView?
- 对高优先级、手动布局的控件采用保留区域 API。
Duo 工艺层(来自 apple-design 技能)
HIG 说明了 什么 自适应。本节将 Apple 的流体界面和设计原则指导(WWDC Designing Fluid Interfaces、Principles of Great Design)应用于在 Duo 上的 如何 感受。这些是应用原则,不是 HIG 规则。有关完整的动画工具包(投影、橡皮筋效果、速度传递),同时加载 Emil Kowalski 的 apple-design 技能(来自 emilkowalski/skills)并将其网页示例转换为 SwiftUI/UIKit。
折叠和调整大小动画
- 折叠是一个连续的、用户驱动的姿势。随之而来的布局变化(窗格宽度均衡、网格重排、内容移离折叠区域)应平滑跟踪铰链且可中断:人们可以在折叠中途停止或反转,因此始终从当前屏幕值开始动画,切勿快照到结束状态。
- 对重排使用临界阻尼弹簧(SwiftUI
.spring(duration: 0.4, bounce: 0)或.smooth;UIKit 使用bounce: 0的UIView.animate(springDuration:bounce:))。无反弹:用户未轻触任何东西,因此过冲看起来像是损坏。 - 跨屏幕的空间一致性:当有人打开设备时,他们在外屏上查看的项目保持锚点(邮件中打开的电子邮件变为尾随窗格,而不是新屏幕)。保持滚动位置和选择;额外的层次结构级别出现在其 旁边。
- 小调整而非重新排列(HIG)与“沿变化方向提供提示”规则相同:元素应可见地滑向新位置,而非传送。
作为材质层的侧边控件
- 侧边工具栏和标签栏浮动在内容之上(默认无滚动边缘效果和背景,根据技术讲座)。不要添加硬分隔线或自己的背景;使用安全区域插页使内容不被栏遮挡。
- 放置在栏中的自定义视图必须在其后滚动的内容和“降低透明度”开启时出现的实体背景上都保持清晰可读。
应用于 Duo 的原则
- 熟悉度:不要覆盖垂直栏的放置;这是平台的新肌肉记忆。
- 分组和映射:控件保持在其影响的窗格旁边(邮件列表控件在列表上方)。
- 寻路:在每种姿态下,人们应仍能回答“我在哪里,如何返回”。返回/关闭始终位于垂直轴的顶部。
- 灵活性:一个自适应布局,Dynamic Type 随之缩放。在带有侧边栏的窄高外屏上测试最大文本大小。
- 响应:姿态变化绝不能阻止输入。折叠过程中的点击仍应生效。
无障碍设计
- 开启“减弱动态效果”时,将重排滑动/弹簧替换为短促的交叉淡入淡出。
- 开启“降低透明度”时,侧边栏变为实体。
- 折叠过程中移动的大表面:保持运动短促,避免大的亮度跳跃。
常见错误
| 错误 | 修复 |
|---|---|
| 为每种姿态定制布局 | 尺寸类别加可调整大小的布局 |
| 隐藏功能 |