优化 Mac Catalyst App 的界面
Optimize the interface of your Mac Catalyst app
2020年6月25日
一句话判断
如果你的 Catalyst App 看起来像个”放大版的 iPad App”,这场 Session 提供了具体的优化路径——从鼠标悬停到键盘快捷键到窗口尺寸适配。
这场 Session 讲了什么
Mac Catalyst 让 iPad App 可以运行在 macOS 上,但默认状态下界面有很多”iOS 痕迹”。Session 讲解了如何让 Catalyst App 看起来更像原生 Mac App。
核心内容包括:UIHoverGestureRecognizer 处理鼠标悬停效果(Mac 用户习惯鼠标划过按钮时有视觉反馈)、UIKeyCommand 和 UIKeyModifierFlags 实现键盘快捷键、窗口尺寸的灵活适配(Mac 窗口可以自由调整大小,不像 iPad 固定比例)。
Session 还介绍了 Catalyst App 的工具栏优化——使用 NSToolbar(通过桥接)替代 iOS 风格的导航栏工具栏,以及如何正确处理侧边栏在窗口大小变化时的折叠/展开。
值得深挖的点
鼠标悬停是 Mac 和 iPad 的核心交互差异。 iPad 上没有 hover 状态,但 Mac 用户期望按钮、列表项等在鼠标划过时有高亮效果。UIHoverGestureRecognizer 是填补这个差距的关键——但它只在 macOS 上触发,iPad 上会自动忽略。
键盘快捷键的系统性设计。 Mac App 必须支持 Cmd+N(新建)、Cmd+S(保存)、Cmd+W(关闭窗口)等标准快捷键。Catalyst App 需要通过 UIKeyCommand 逐一注册这些快捷键。Session 建议创建一个专门的 ShortcutManager 来集中管理所有快捷键映射。
代码片段
import UIKit
// 鼠标悬停效果
class HoverButton: UIButton {
override init(frame: CGRect) {
super.init(frame: frame)
setupHover()
}
private func setupHover() {
let hoverGesture = UIHoverGestureRecognizer(
target: self,
action: #selector(handleHover(_:))
)
addGestureRecognizer(hoverGesture)
}
@objc private func handleHover(_ gesture: UIHoverGestureRecognizer) {
switch gesture.state {
case .began, .changed:
// 鼠标进入按钮区域
backgroundColor = .systemFill
layer.shadowOpacity = 0.2
case .ended:
// 鼠标离开
backgroundColor = .systemBackground
layer.shadowOpacity = 0
default:
break
}
}
}
// 键盘快捷键
class DocumentViewController: UIViewController {
override var keyCommands: [UIKeyCommand]? {
return [
UIKeyCommand(
title: "新建文档",
action: #selector(newDocument),
input: "n",
modifierFlags: .command
),
UIKeyCommand(
title: "保存",
action: #selector(saveDocument),
input: "s",
modifierFlags: .command
),
UIKeyCommand(
title: "关闭窗口",
action: #selector(closeWindow),
input: "w",
modifierFlags: .command
),
UIKeyCommand(
title: "撤销",
action: #selector(undo),
input: "z",
modifierFlags: .command
)
]
}
@objc func newDocument() { /* ... */ }
@objc func saveDocument() { /* ... */ }
@objc func closeWindow() { /* ... */ }
@objc func undo() { /* ... */ }
}
// 窗口尺寸适配
class AdaptiveSplitViewController: UISplitViewController {
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
// Mac 窗口可以很窄,需要处理侧边栏的自动折叠
if size.width < 700 {
// 窄窗口:隐藏侧边栏
preferredDisplayMode = .secondaryOnly
} else {
// 宽窗口:显示侧边栏
preferredDisplayMode = .oneBesideSecondary
}
}
}
最佳实践
- 为所有可交互元素添加 hover 效果。 Mac 用户期望按钮、列表项、工具栏图标在鼠标悬停时有视觉反馈。
- 注册标准的 Cmd 快捷键。 至少支持 Cmd+N/S/W/Z/Q,覆盖新建、保存、关闭、撤销、退出。
- 测试各种窗口尺寸。 从最小窗口到全屏,确保布局不会崩溃或出现奇怪的空白。
- 使用 NSToolbar 替代 iOS 风格的导航栏。 Mac 用户期望窗口顶部有原生风格的工具栏。
还有什么值得关注
- macOS Big Sur 的 Catalyst App 可以使用新的 Sidebar 样式
UITrackingLayoutGuide可以帮助实现窗口大小变化的自动布局适配- Catalyst App 可以通过 Plugin 桥接使用部分 AppKit 控件
- 右键菜单(Context Menu)在 Mac 上更常用,确保所有列表项都支持