聚焦 iPad 键盘导航
Focus on iPad keyboard navigation
2021年6月10日
一句话判断
iPadOS 15 的全键盘访问(Full Keyboard Access)让用户完全不用触摸屏幕就能操作你的 App——但前提是你的 App 正确支持了焦点系统(Focus System)。
这场 Session 讲了什么
Session 讲解了 iPadOS 15 中改进的键盘导航系统。iPad 连接硬件键盘后,用户可以通过 Tab 键和方向键导航 App 的界面元素,用 Enter 键激活按钮,用 Escape 键关闭弹窗。这就是 Full Keyboard Access。
SwiftUI 在 iOS 15 中新增了 @FocusState 属性包装器和 .focused() 修饰符,让你以声明式方式管理焦点。UIKit 方面,UIFocusSystem 在 iPadOS 15 中也做了增强,支持更灵活的焦点移动策略。
Session 还强调了键盘导航对无障碍的重要性——很多运动障碍用户依赖键盘操作,VoiceOver 用户也会使用键盘辅助导航。支持键盘导航不只是”加分项”,而是无障碍合规的基本要求。
值得深挖的点
焦点环(Focus Ring)的视觉反馈
当用户通过键盘导航时,被聚焦的元素周围会显示系统级的焦点环(蓝色光环)。这个焦点环由系统绘制,你不需要自己画。但你需要确保你的自定义控件正确响应焦点变化——改变背景色或添加边框来加强视觉反馈。SwiftUI 的 .focused() 修饰符会自动处理焦点环的显示。
焦点顺序的控制
默认的焦点顺序是从左到右、从上到下。但你可能需要自定义——比如表单中应该先跳到必填字段,跳过只读的标签。SwiftUI 的 @FocusState 让你用编程方式控制焦点位置。UIKit 的 UIFocusEnvironment 协议让你定义自定义的焦点搜索路径。
代码片段
SwiftUI 的焦点管理
struct LoginForm: View {
enum Field: Hashable {
case username, password
}
@FocusState private var focusedField: Field?
@State private var username = ""
@State private var password = ""
var body: some View {
VStack {
TextField("用户名", text: $username)
.focused($focusedField, equals: .username)
.onSubmit { focusedField = .password }
SecureField("密码", text: $password)
.focused($focusedField, equals: .password)
.onSubmit { login() }
Button("登录") { login() }
// Tab 键会自动跳转到下一个可聚焦元素
}
.onAppear { focusedField = .username }
}
}
自定义焦点顺序
struct SettingsForm: View {
@FocusState private var focusedSection: Section?
enum Section: Hashable {
case general, privacy, notifications
}
var body: some View {
Form {
Section("通用") {
Toggle("深色模式", isOn: $darkMode)
.focused($focusedSection, equals: .general)
}
Section("隐私") {
Toggle("分析数据", isOn: $analytics)
.focused($focusedSection, equals: .privacy)
}
}
// 快捷键跳转到不同 section
.onKeyPress(.init("1"), action: { focusedSection = .general })
.onKeyPress(.init("2"), action: { focusedSection = .privacy })
}
}
UIKit 的焦点环境
class CustomControl: UIControl {
// 标记为可聚焦
override var canBecomeFocused: Bool { true }
// 焦点变化时的视觉反馈
override func didUpdateFocus(in context: UIFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) {
super.didUpdateFocus(in: context, with: coordinator)
coordinator.addCoordinatedAnimations {
if self.isFocused {
// 被聚焦:添加高亮
self.backgroundColor = .systemBlue.withAlphaComponent(0.1)
self.layer.borderWidth = 2
self.layer.borderColor = UIColor.systemBlue.cgColor
} else {
// 失去焦点:恢复
self.backgroundColor = .clear
self.layer.borderWidth = 0
}
}
}
}
最佳实践
测试键盘导航: 在 iPad 上连接 Smart Keyboard 或蓝牙键盘。打开设置 > 辅助功能 > 键盘 > 全键盘访问。然后用 Tab/Shift+Tab 导航你的 App,确保每个交互元素都能被聚焦和激活。
SwiftUI 优先: SwiftUI 的 @FocusState 比 UIKit 的 UIFocusSystem 更好用。新项目用 SwiftUI 构建表单和设置界面,自动获得键盘导航支持。UIKit 项目中的自定义控件需要手动实现 canBecomeFocused 和 didUpdateFocus。
还有什么值得关注
- iPadOS 15 支持用键盘快捷键触发 UI 元素(如 Tab 切换分栏视图)。
- SwiftUI 的
.onKeyPress修饰符可以响应特定按键。 - VoiceOver 用户可以同时使用键盘导航和 VoiceOver 手势,两者互不干扰。