Highlight
SwiftUI 在 macOS Sequoia 新增了
.toolbarBackgroundVisibility()、.windowMinimizeBehavior()、.defaultWindowPlacement()等窗口定制 API,无需 NSWindow bridging 即可实现隐藏标题栏、禁用最小化按钮、动态计算窗口位置等功能(02:02)。
核心内容
Session 以 Destination Video 示例 App 展示如何为不同类型的窗口定制外观和行为。开发者面临的问题是:SwiftUI 的默认窗口样式不够灵活——视频播放器需要根据内容动态计算尺寸,About 窗口不需要最小化按钮,主窗口希望内容延伸到顶部边缘。这些需求之前都需要写 NSWindow 的 Objective-C bridging 代码。
Apple 在 macOS Sequoia 中引入了三类新 API:Toolbar 定制可隐藏标题和工具栏背景、窗口行为控制可禁用最小化按钮和状态恢复、窗口位置控制可根据内容尺寸和屏幕尺寸动态计算窗口的理想位置。
详细内容
Toolbar 定制
Destination Video 的主窗口有一个大图需要延伸到窗口顶部边缘。默认情况下,toolbar 和标题区域会占据顶部空间(03:00)。
WindowGroup("Destination Video", id: "main") {
MainView()
.toolbar(removing: .title)
.toolbarBackgroundVisibility(.hidden, for: .windowToolbar)
}
.toolbar(removing: .title)隐藏窗口标题栏(标题仍保留在窗口元数据中,主菜单和无障碍功能会继续使用).toolbarBackgroundVisibility(.hidden, for: .windowToolbar)移除工具栏背景,让内容延伸到窗口顶部边缘
窗口行为控制
About 窗口显示静态信息,从主菜单随时可达,不需要最小化按钮和状态恢复(05:12)。
Window("About Destination Video", id: "about") {
AboutView()
.toolbar(removing: .title)
.toolbarBackgroundVisibility(.hidden, for: .windowToolbar)
.containerBackground(.thickMaterial, for: .window)
.windowMinimizeBehavior(.disabled)
.restorationBehavior(.disabled)
}
.containerBackground(.thickMaterial, for: .window)用毛玻璃材质替换默认背景颜色.windowMinimizeBehavior(.disabled)禁用黄色最小化按钮.restorationBehavior(.disabled)关闭状态恢复(App 退出后不会自动重开此窗口)
窗口位置控制
视频播放器窗口需要根据视频尺寸和屏幕尺寸动态计算位置和大小(07:02)。
Window("Video Player", id: "player") {
PlayerView(video: video)
.defaultWindowPlacement { content, context in
let idealSize = content.sizeThatFits(.unspecified)
let visibleRect = context.display.visibleRect
let size = idealSize.clamped(to: visibleRect.size)
return .default(.center, size: size)
}
.windowIdealPlacement { content, context in
let visibleRect = context.display.visibleRect
let zoomedSize = zoomToFit(content.sizeThatFits(.unspecified), in: visibleRect.size)
return .default(.center, size: zoomedSize)
}
}
.defaultWindowPlacement()设置新窗口的初始位置和尺寸content.sizeThatFits()计算内容理想尺寸context.display.visibleRect获取屏幕可用区域(自动扣除菜单栏和 Dock 占用空间).clamped(to:)确保窗口不超出屏幕边界
.windowIdealPlacement()控制用户点击 Zoom 按钮后的窗口尺寸zoomToFit()自定义函数,在保持宽高比前提下最大化窗口
关键点:
- 视频以原生尺寸显示,超出屏幕时自动缩小适应
- 窗口默认居中显示
- Zoom 行为可自定义,不再受系统默认逻辑限制
核心启发
1. 为每种窗口类型定制独立配置
主窗口、About 窗口、设置窗口、播放器窗口的 toolbar 需求、最小化行为、状态恢复策略都应该不同。花 10 分钟为每种窗口添加合适的 modifier,用户体验会明显提升。
2. 优先迁移用户最易感知的改动
.toolbarBackgroundVisibility(.hidden) 让内容布局更自由,.defaultWindowPlacement() 修正初始窗口大小。这两个改动迁移成本最低,用户感知最强。状态恢复和最小化行为的修改更谨慎,因为它们改变了用户已有的操作习惯。
3. 利用新 API 避免跨语言桥接
之前需要写 NSWindow 的 Objective-C bridging 代码实现的需求,现在 SwiftUI 都有原生的 modifier。新项目优先用 SwiftUI API,维护成本更低。
关联 Session
- Bring multiple windows to your SwiftUI app — 深入讲解 Window、WindowGroup 等不同 Scene 类型的使用场景
- Work with windows in SwiftUI — 系统介绍 SwiftUI 窗口管理 API 与最佳实践
- Meet SwiftUI — SwiftUI 概览,包含 macOS 适配内容
- Bring your app to the desktop — macOS App 适配与桌面体验设计
评论
GitHub Issues · utterances