这是「iPhone Duo 六支苹果官方 Tech Talks 视频」系列的第三篇,前两篇分别讲设计原则和适配准备,后面还会聊自适应布局、多屏与相机。这一篇聚焦工具栏和标签栏:为什么它们在 iPhone Duo 上会立到侧边,以及怎样让现有界面顺着系统规则工作。

为什么工具栏要移到侧边

iPhone Duo 的外屏比例更宽。若继续把控件堆在顶部和底部,横向空间没有被利用,垂直内容反而会被压缩。系统因此把通常位于上下边缘的控件放到侧边,让内容多留一点高度,操作也仍然在手指容易触及的位置。

在外屏横屏和展开后的内屏横屏状态下,工具栏和导航栏可以垂直排列。设备竖屏展开时,大屏回到熟悉的 iPhone 布局,显示水平状态栏。同一组内容会随布局改变方向。

更宽的比例把原本位于上下边缘的控件带到侧边

先用最新的 SDK 重新构建应用,再检查工具栏是否来自导航容器,而不是自绘区域。

先让系统接管 bar

SwiftUI 中,把 toolbar 修饰符和 NavigationStack 或 NavigationSplitView 搭配使用;需要标签栏时,使用 TabView 提供的工具栏。UIKit 中优先采用 UINavigationController 和 UITabBarController,由它们管理相应的导航栏、工具栏和标签栏。

UIKit 的项目应设置在视图控制器上,再把视图控制器放进导航控制器。不要另外创建自定义的 UIToolbar。若自己构建 UIToolbar、UINavigationBar 或 UITabBar,系统不会把这些子组件中的内容当作导航容器提供的项目来处理,垂直排列、合并和溢出也就不会按这套规则工作。

用导航容器提供工具栏:SwiftUI 与 UIKit 的入口

应用已经支持调整大小却仍显示水平工具栏,先检查 SDK 和容器归属。

共享区域不是一条独立的栏

导航控件、工具栏和标签栏会在同一个共享 bar 区域内共存。可以把原来的上下布局想象成旋转 90 度后的垂直堆栈。不同容器参与的部分不同:备忘录可能只有工具栏,时钟使用标签栏,健身则同时使用两者。

分屏视图中只有 detail 列参与垂直移动,其他列仍保持水平排列。detail 列已有垂直栏时,展开界面不会再额外放检查器垂直栏。

导航、工具栏和标签栏共享同一块区域

工具栏只有在容器位于显示屏边缘时,项目才会垂直移动。外屏中,视图的工具栏显示在侧边;内屏默认放在中央,项目仍水平排列。使用 preferredPlacement API 改变位置时,右侧视图会显示垂直栏,左侧视图不会。栏与硬件边缘对齐,从右到左的语言环境也保持在设备同一侧。

不要强行把每个控件改成垂直,先保持它与容器的关联。

项目顺序:顶部先放导航

垂直栏的顺序要先安排最常用、也最需要稳定位置的动作。顶部留给返回或关闭;其后放完成这类醒目的操作。其余项目保留原来的分组,合并到同一个工具栏后,分组之间仍会用垂直间隔符分开。

如果使用导航控制器,系统会自动添加返回按钮。SwiftUI 中的自定义返回或关闭按钮使用 cancellationAction 布局;UIKit 中使用 leading item,并让 leftItemSupplementsBackButton 保持 false,这也是默认值。需要固定在顶部的突出操作,SwiftUI 使用 topBarPinnedTrailing 布局,UIKit 使用 pinnedTrailingGroup 布局。

返回、关闭这类主操作放在垂直栏顶部

并非所有姿态都会显示垂直栏,返回和关闭的位置仍要保持可预测。

先准备好工具栏内容

水平工具栏的项目高度固定、宽度可以变化;垂直工具栏正好相反:宽度固定,高度可以变化。因此,侧边栏更适合纯符号项目。返回、分享这类动作通常有明确图标,适合沿垂直轴排列;只有“编辑”这样的纯文字项目,仍然适合留在水平轴上。

给每个项目同时提供图标和标题。系统会根据上下文选择呈现形式:水平栏优先使用图标,没有图标才显示文本;项目进入溢出菜单后,标题和图标都会出现。SwiftUI 的标签,以及 UIKit 中 UIBarButtonItem 的标题和图片属性,已经足够。平时只显示图片也不要省掉标题。

默认情况下,SwiftUI 和 UIKit 会根据项目内容推断轴向。若一个项目会在符号和文字之间切换,或者自定义控件有明确的方向要求,可以使用新的 AxisBehavior API 调整默认行为。

编辑按钮不要只因为有图标就塞进垂直栏。系统编辑按钮会自动保持在水平栏中;自定义控件使用“仅水平轴”行为。UIKit 中确实适合垂直显示的自定义视图,例如指南针视图,则设置“首选垂直轴”行为。

纯符号优先,自定义视图要自适应

减少只显示标题的项目,也少用同时放文字和图片的自定义视图。先问一个实际问题:文字是在解释符号,还是携带独立的信息?如果只是补充,符号通常已经足够;如果文字承载金额等信息,就把这个控件留在水平栏中。购物车旁的金额便属于后一种情况。

计数也可以从内联文字移到徽章。收件箱用徽章显示未读数量后,项目可以只保留图标,在垂直栏里更紧凑。iOS 26 新增的徽章 API 应优先采用,这样不同设备上的外观由系统统一处理。辅助栏仍应与键盘绑定,不要把它移到垂直轴上。

徽章 API 把带计数的项目收缩成纯图标

自定义视图要能适应固定栏宽,或本身具备垂直自适应布局。比如操作面板在垂直显示时可以隐藏标题、缩短高度。

自定义视图还需要知道当前是否处于垂直栏。SwiftUI 可以读取 toolbarVerticalEdge 环境属性,UIKit 可以读取对应的 trait。项目可位于垂直轴时,这个值会被填充;否则是 nil 或未指定。

垂直栏默认没有滚动边缘效果。启用“降低透明度”辅助功能设置后,它会显示背景,自定义内容在两种状态下都要清晰。弹性间隔符在垂直轴上的默认大小为零,固定间隔符保留最小尺寸。应用不应再额外添加间距。

自定义视图在垂直栏里隐藏标题、调整高度

溢出菜单要有明确的优先级

横屏外屏的垂直空间更少,工具栏更容易溢出。键盘出现时也会挤占空间;竖屏使用画中画时,工具栏同样可能需要收起项目。先决定工具栏和标签栏哪个更该保持可见。

以导航为中心的界面,例如 Podcasts,工具栏默认优先压缩,让主要导航目标继续可访问。游戏应用这类任务导向界面会优先压缩标签栏,保留频繁使用的操作。每个视图的偏好可以通过 toolbarCompressionBehavior API 配置。

如果应用已有自己的溢出菜单,应把操作并入系统管理的菜单。SwiftUI 使用 ToolbarOverflowMenu,UIKit 使用 additionalOverflowItems。省略号是 iPhone 上的标准溢出符号,其他菜单使用各自明确的符号。

空间不足时项目进入系统溢出菜单

默认情况下,项目从下往上进入溢出区域。对每个项目使用 visibilityPriority API,可以分配高、低或自定义优先级,控制折叠顺序。设置时先按组排序,再在需要时调整组内项目。

优先级应来自真实使用频率。邮件里的撰写、备忘录里的新建备忘录,应该尽量最后才移入溢出区域;带徽章的状态项目也要多留在栏上。系统不知道哪个操作更重要,需要开发者明确声明。

什么时候应该退出垂直布局

垂直栏是大多数应用的默认方向,但不是硬规则。计算器这类单页应用,底部有大量内容,水平布局可能更合适,因为它能把内容完整展开。一个弹出窗格如果只有关闭按钮,垂直栏反而会占掉一块本可用于内容的空间,也可以考虑保持水平。

SwiftUI 使用 toolbarVerticalBehavior,UIKit 使用 preferredVerticalBarBehavior 来禁用垂直工具栏行为。判断标准是侧边栏是否真的给当前页面带来空间或操作上的好处。

单页应用可以退出垂直布局,继续用水平工具栏

适配清单

把 iPhone Duo 支持落到代码和界面上,可以按这个顺序检查:

  • 用最新 SDK 重新构建,确认工具栏来自 TabView、NavigationStack 或 NavigationSplitView;UIKit 优先检查 UINavigationController 和 UITabBarController。
  • 画出每个 bar 的项目顺序,把返回或关闭放在顶部,完成等突出操作紧随其后。
  • 为项目同时提供图标和标题,清理只显示标题或同时塞入文字与图片的自定义视图。
  • toolbarVerticalEdge、AxisBehavior 和徽章处理方向与内容,再用 visibilityPriority 设定溢出顺序。
  • 测试外屏横屏、内屏横屏、竖屏展开、键盘和画中画;对计算器或单按钮弹窗这类页面,再决定是否用 toolbarVerticalBehavior 或 preferredVerticalBarBehavior 退出垂直布局。

工具栏并没有换成一套全新的控件,变化的是它所在的轴和可用空间。把内容交给正确的导航容器,补齐标题,处理好自定义视图与溢出优先级,现有界面就能在 iPhone Duo 的不同姿态之间保持同一套操作逻辑。

系列文章

这套教程一共六篇,对应苹果官方的六支 Tech Talks 视频: