Accessibility 进阶 20m
在你的 iOS App 中支持全键盘访问
Support Full Keyboard Access in your iOS app
2021年6月11日
一句话判断
iOS 15 正式支持 Full Keyboard Access(全键盘操作)—— iPad 键盘用户可以不用触摸屏就完成所有操作,这对 motor impairment 用户是刚需,对效率型用户是加分项,但你需要在代码中正确处理焦点(Focus)和键盘快捷键。
这场 Session 讲了什么
iOS 15 引入了 Full Keyboard Access 模式,用户可以通过外接键盘(Smart Keyboard、Magic Keyboard、第三方蓝牙键盘)完全控制 iPad 和 iPhone,不需要触摸屏幕。
Session 讲解了:
- 焦点系统(Focus System):键盘焦点(Keyboard Focus)和 VoiceOver 焦点是两套独立的系统。Tab 键移动键盘焦点,VoiceOver 的手势移动 VoiceOver 焦点。
- 焦点环(Focus Ring):获得焦点的控件会显示蓝色的焦点环,系统自动管理大部分 UIKit 控件的焦点行为。
- 自定义焦点顺序:默认按从左到右、从上到下的顺序,但可以通过
shouldUpdateFocus和didUpdateFocus自定义。 - 键盘快捷键(Key Commands):
UIKeyCommand让你添加自定义快捷键(如 Cmd+N 新建、Cmd+S 保存)。
值得深挖的点
键盘焦点 vs VoiceOver 焦点的区别。这是最容易混淆的部分。键盘焦点由 Tab/Shift+Tab 移动,只响应键盘事件。VoiceOver 焦点由 VoiceOver 手势控制(左右滑动)。两者可以同时指向不同元素。当 VoiceOver 开启时,键盘焦点跟随 VoiceOver 焦点;VoiceOver 关闭时,只有键盘焦点。你的 app 需要正确处理这两种焦点状态的 UI 反馈。
SwiftUI 的焦点管理。SwiftUI 在 iOS 15 中新增了 @FocusState 属性包装器,可以编程控制焦点。配合 focused(_:) 修饰符,你可以指定哪个元素获得焦点,也可以响应焦点变更。这对表单场景特别有用 —— 按 Tab 键在输入框之间移动、提交后自动聚焦到下一个字段。
代码片段
SwiftUI 的焦点管理:
import SwiftUI
struct LoginFormView: View {
@State private var username = ""
@State private var password = ""
// 控制焦点位置
@FocusState private var focusedField: Field?
enum Field: Hashable {
case username, password, submitButton
}
var body: some View {
Form {
TextField("用户名", text: $username)
.focused($focusedField, equals: .username)
.onSubmit {
// 按 Enter 跳转到密码框
focusedField = .password
}
SecureField("密码", text: $password)
.focused($focusedField, equals: .password)
.onSubmit {
// 按 Enter 提交
focusedField = .submitButton
performLogin()
}
Button("登录") {
performLogin()
}
.focused($focusedField, equals: .submitButton)
}
// 页面出现时自动聚焦到用户名
.onAppear {
focusedField = .username
}
}
}
UIKit 中自定义焦点行为:
import UIKit
class FormViewController: UIViewController {
var usernameField: UITextField!
var passwordField: UITextField!
var loginButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
setupKeyCommands()
}
// 添加键盘快捷键
override var keyCommands: [UIKeyCommand]? {
return [
UIKeyCommand(
input: "\r", // Enter 键
modifierFlags: .command,
action: #selector(handleLoginShortcut),
title: "登录"
),
UIKeyCommand(
input: "n",
modifierFlags: [.command, .shift],
action: #selector(handleNewAccountShortcut),
title: "创建新账号"
)
]
}
// 自定义焦点移动顺序
override func shouldUpdateFocus(in context: UIFocusUpdateContext) -> Bool {
// 不允许焦点回到已禁用的控件
if context.nextFocusedView == loginButton, !loginButton.isEnabled {
return false
}
return true
}
@objc func handleLoginShortcut() {
performLogin()
}
@objc func handleNewAccountShortcut() {
showRegistrationFlow()
}
}
全局键盘快捷键:
import SwiftUI
struct ContentView: View {
@State private var showSearch = false
var body: some View {
NavigationView {
List {
// 内容...
}
.searchable(text: .constant(""), isPresented: $showSearch)
// Cmd+F 打开搜索
.keyboardShortcut("f", modifiers: .command)
}
.onKeyPress(.returnKeyPress) {
print("Enter 被按下")
return .handled
}
}
}
最佳实践
- 所有可交互控件都要能通过键盘访问。自定义视图(如卡片式 UI)需要手动添加
isAccessibilityElement和canBecomeFocused支持。 - 焦点环不要隐藏。有些设计师觉得蓝色焦点环不好看,要求去掉。这是无障碍的硬性需求,不能为了美观牺牲可用性。
- 添加
Cmd+,快捷键打开设置、Cmd+W关闭面板、Cmd+N新建。遵循 macOS 的键盘快捷键惯例,iPad 用户已经有这些肌肉记忆。
还有什么值得关注
- iOS 15 的 Full Keyboard Access 支持 Tab 导航、Space 激活、Esc 取消等标准键盘操作。
UIFocusSystem在 UIKit 中提供了完整的焦点查询和编程控制 API。- 键盘快捷键会在 Menu Bar(iPadOS 15 新增)中自动展示。
WWDC 2021