Highlight
Apple 在 visionOS 上为 SwiftUI 提供了自动适配的玻璃背景、动态缩放、vibrancy 材质和 hover effect 等能力,让现有的多平台 SwiftUI 应用几乎零改动就能在 Shared Space 中运行,同时通过 ornament、vector asset 等少量调整即可充分利用空间计算平台的独特交互方式。
核心内容
从 iPad 到 visionOS:一步之遥
你有一个支持 iPhone、iPad、Mac 和 Apple Watch 的 SwiftUI 应用,想让它在 visionOS 上运行。过去,适配一个新平台意味着重写大量 UI 代码。visionOS 不同——SwiftUI 从设计之初就考虑了这个平台。
在 Xcode 的 Supported Platforms 菜单中添加 visionOS,应用就能在模拟器中运行。布局保持 iPad 风格,但细节已经变了:窗口有了玻璃背景,导航栏按钮变成圆形,列表行在注视时会高亮。这些变化全部由 SwiftUI 自动处理。
(02:51)
玻璃与 Vibrancy:没有 Light/Dark 的世界
visionOS 不区分浅色和深色模式。玻璃背景会根据环境光线和背后物体的颜色自动调整对比度。这意味着你不能再依赖 colorScheme 检查来为不同模式设置不同颜色。
Solid color(纯色)在玻璃上表现固定,无法适应环境变化。SwiftUI 的 semantic styles(语义化样式)会自动采用 vibrancy 材质,在玻璃上保持可读性。将自定义视图的背景从纯色改为 .fill 等语义样式后,代码更简洁,视觉效果在所有平台上都更正确。
(06:58)
Hover Effect:空间交互的视觉反馈
visionOS 有四种交互方式:间接捏合(最常用)、直接触摸、触控板指针、辅助功能。无论哪种方式,可交互内容都需要 hover effect 来提供视觉反馈。
SwiftUI 的系统控件自动带有 hover effect。自定义的可交互视图需要手动添加:
// 为自定义可交互视图添加 hover effect
BirdView()
.hoverEffect()
关键点:
hoverEffect()默认提供高亮效果,注视时视图会微微变亮- 系统 hover effect 在应用进程外执行,保护用户隐私——应用无法直接获取用户的注视位置
- 应用只能收到捏合、触摸、悬停手指或指针的事件
如果 hover effect 的边界形状不理想,可以用 contentShape 修饰符自定义:
BirdView()
.contentShape(.hoverEffect, RoundedRectangle(cornerRadius: 12))
.hoverEffect()
关键点:
contentShape(.hoverEffect, ...)指定 hover effect 的形状和边界- 这里使用圆角矩形,让 hover effect 有圆角和适当内边距
更好的做法是将可交互视图直接改为 Button:
Button(action: showBirdDetails) {
BirdView()
}
.buttonStyle(.plain)
关键点:
Button在 visionOS 上默认有边框,使用.plain样式可去掉背景- Plain button 自动获得标准 hover effect 和点击缩放动画
(10:16)
Ornament:窗口外的控件
visionOS 的窗口不受屏幕尺寸限制,控件也不必局限在窗口内部。Ornament 是一种附着在窗口边缘的控件容器,常用于放置辅助功能。
TabView 在 visionOS 上会自动变成 ornament,附着在窗口左侧。平时收起,注视图标时展开显示标签。
Toolbar 也可以通过 .bottomOrnament placement 变成 ornament:
.toolbar {
ToolbarItem(placement: .bottomOrnament) {
TimeRangePicker()
}
}
自定义 ornament 使用 ornament() 修饰符:
.ornament(
attachmentAnchor: .scene(.bottom),
contentAlignment: .center
) {
NotificationBanner()
.glassBackgroundEffect()
}
关键点:
attachmentAnchor: .scene(.bottom)将 ornament 附着在窗口底部contentAlignment: .center让 ornament 中心与锚点对齐- 自定义 ornament 默认没有玻璃背景,需要手动添加
.glassBackgroundEffect()
(13:34)
详细内容
Vector Asset:动态缩放的关键
visionOS 中的应用可能离你很远,也可能被拉近到眼前,还可能从侧面观看。系统通过动态缩放确保内容在任何距离都清晰。这要求你提供矢量资源。
文本和 SF Symbols 已经是矢量。自定义图标和图形需要在 Asset Catalog 中设置为 Single Scale,并勾选 Preserve Vector Data:
Asset Catalog 设置:
- Scales: Single Scale
- Preserve Vector Data: ✅
Bitmap 图片在放大时会模糊。将位图替换为矢量图后,无论用户靠近还是远离,图形始终保持锐利。
(05:52)
从 NavigationSplitView 到 TabView
iPad 上,Regular 水平尺寸类优先使用 sidebar。visionOS 上窗口尺寸不受限制,sidebar 占用内容空间。TabView 是更好的选择:
TabView {
BackyardsView()
.tabItem {
Label("Backyards", systemImage: "tree")
}
PlantsView()
.tabItem {
Label("Plants", systemImage: "leaf")
}
BirdsView()
.tabItem {
Label("Birds", systemImage: "bird")
}
}
关键点:
- TabView 在 visionOS 上自动显示为左侧 ornament
- 每个 tab item 需要标题和图标
- 未交互时 tab bar 收起,节省内容空间
(12:15)
核心启发
-
做什么:将现有的 iPad SwiftUI 应用移植到 visionOS
- 为什么值得做:只需在 Xcode 中添加 visionOS 目标,应用就能在 Shared Space 中运行。SwiftUI 自动处理玻璃背景、控件适配和 hover effect,移植成本极低
- 怎么开始:打开项目设置,在 Supported Platforms 中添加 visionOS,在模拟器中运行并观察自动适配效果
-
做什么:为应用设计一个自定义 ornament 通知系统
- 为什么值得做:ornament 可以附着在窗口外部,不占用内容区域。适合放置状态提示、快捷操作等辅助信息
- 怎么开始:使用
.ornament(attachmentAnchor:contentAlignment:content:)修饰符,结合.glassBackgroundEffect()创建悬浮通知
-
做什么:用矢量图形替换应用中的所有位图图标
- 为什么值得做:visionOS 上应用可能被用户拉近到眼前,位图会暴露像素。矢量图在任何缩放级别都保持清晰
- 怎么开始:检查 Asset Catalog,将多 scale 位图替换为 Single Scale 矢量图,勾选 Preserve Vector Data
-
做什么:审查应用中所有基于
colorScheme的条件渲染逻辑- 为什么值得做:visionOS 不区分 light/dark,且玻璃背景会动态变化。solid color 无法适应环境,semantic styles 和 vibrancy 才是正确方案
- 怎么开始:搜索代码中的
.colorScheme和Color(...)硬编码,替换为.fill、.background等语义化样式
-
做什么:为所有自定义可交互控件添加 hover effect
- 为什么值得做:空间计算中用户通过注视选择目标,hover effect 是确认”这个控件可以交互”的关键视觉反馈。缺少它会让用户感到困惑
- 怎么开始:优先将可点击视图改为
Button,对无法改用的视图添加.hoverEffect()和.contentShape(.hoverEffect, ...)
关联 Session
- Meet SwiftUI for spatial computing — SwiftUI spatial computing 入门,了解平台基础概念
- Take SwiftUI to the next dimension — 在 SwiftUI 中使用 3D 内容和 Volume
- Go beyond the window with SwiftUI — 使用 Immersive Space 创建沉浸式空间体验
- Meet UIKit for spatial computing — 基于 UIKit 的应用如何适配 visionOS
评论
GitHub Issues · utterances