在 SwiftUI 中检测按键事件。
在 SwiftUI 中检测按键事件允许你响应键盘键,如回车(输入)、shift、command 等。虽然大多数 Mac 应用程序使用键盘事件,但你必须 考虑为 iPad 应用程序添加支持,因为可以使用外部键盘。
响应按键事件
SwiftUI 提供了几个 onkeyPress
修饰符,允许你侦听特定键或一组键。在我们深入探讨示例之前,重要的是要意识到你的视图必须处于焦点状态才能接收事件。
以下视图演示了一个没有焦点修饰符的纯文本视图。onKeyPress
事件将不起作用:
struct KeyboardEventsListenerView: View {
var body: some View {
Text("让我们来侦听键盘事件!")
.padding()
.onKeyPress(.return) {
/// 不会被调用,因为 Text 元素没有焦点。
print("按下了回车键!")
return .handled
}
}
}
我们可以通过使文本元素可聚焦并在出现时启用其焦点状态来解决此问题:
struct KeyboardEventsListenerView: View {
@FocusState private var isFocused: Bool
var body: some View {
Text("让我们来侦听键盘事件!")
.padding()
.focusable()
.focused($isFocused)
.onKeyPress(.return) {
print("按下了回车键!")
return .handled
}
.onAppear {
isFocused = true
}
}
}
如何侦听特定按键事件?
你可以使用以下 onKeyPress
修饰符来侦听特定的按键事件:
.onKeyPress(.return) {
print("按下了回车键!")
return .handled
}
如何侦听任何按键事件?
如果你想侦听任何键盘按下事件,可以使用以下修饰符:
.onKeyPress(action: { keyPress in
print("""
新的按键事件:
键:\(keyPress.characters)
修饰符:\(keyPress.modifiers)
阶段:\(keyPress.phase)
调试描述:\(keyPress.debugDescription)
""")
return .handled
})
修饰符处理程序提供了一个包含按键事件信息的 keyPress 变量。上面的代码示例方便地打印出这些属性,这将产生以下打印示例:
.onKeyPress(action: { keyPress in
print("""
New key event:
Key: \(keyPress.characters)
Modifiers: \(keyPress.modifiers)
Phase: \(keyPress.phase)
Debug description: \(keyPress.debugDescription)
""")
return .handled
})
在本例中,我按下了 SHIFT + CMD + S
。调试打印显示事件修饰符为原始值,因为我们正在处理一个 OptionSet。你可以使用 characters
属性来查找键,并使用 phase
属性来获取按键事件的阶段(.down
、.repeat
或 .up
)。
侦听按键按下、抬起或重复事件
SwiftUI 的 onKeyPress 修饰符默认只侦听按下阶段的按键事件。如果你想侦听按键抬起事件,可以使用 phases 属性:
.onKeyPress(phases: .up, action: { keyPress in
print("释放了键 \(keyPress.characters)")
return .handled
})
你还可以侦听重复的键盘事件。在这种情况下,只有当用户长时间按住键盘事件时,才会调用处理程序:
.onKeyPress(phases: .repeat, action: { keyPress in
print("键 \(keyPress.characters) 重复!")
return .handled
})
如何侦听一组特定的字符?
你可以侦听一组特定的字符来忽略其他键。例如,你可能只想侦听数字按键事件:
.onKeyPress(characters: .decimalDigits, phases: .up, action: { keyPress in
print("释放了键 \(keyPress.characters)")
return .handled
})
在上面的代码示例中,我们只侦听十进制数字抬起事件。
当 onKeyPress 修饰符不起作用时该怎么办?
在使用 onKeyPress
修饰符侦听按键事件后,你可能不会收到任何回调。如前所述,重要的是确保包含修饰符的视图当前具有焦点。你可以通过使用 focusable()
和 focused($isFocused)
修饰符来实现此目的:
struct KeyboardEventsListenerView: View {
@FocusState private var isFocused: Bool
var body: some View {
Text("让我们来侦听键盘事件!")
.padding()
.focusable()
.focused($isFocused)
.onKeyPress(characters: .decimalDigits, phases: .up, action: { keyPress in
print("释放了键 \(keyPress.characters)")
return .handled
})
.onAppear {
isFocused = true
}
}
}
添加这些修饰符后,你可能会注意到视图周围有一个焦点效果:
具有焦点的视图会接收按键事件,但可能会显示不需要的焦点效果。
你可以使用 .focusEffectDisabled()
修饰符禁用此效果:
struct KeyboardEventsListenerView: View {
@FocusState private var isFocused: Bool
var body: some View {
Text("让我们来侦听键盘事件!")
.padding()
.focusable()
.focused($isFocused)
.focusEffectDisabled()
.onKeyPress(characters: .decimalDigits, phases: .up, action: { keyPress in
print("释放了键 \(keyPress.characters)")
return .handled
})
.onAppear {
isFocused = true
}
}
}
你现在已经创建了一个侦听数字按键抬起事件的视图,同时不会指示正在聚焦。
如果父视图侦听键盘事件,你可能仍然收不到任何按键事件。每个 onKeyPress
修饰符处理程序都必须返回一个结果,即 .handled
或 .ignored
。如果父视图返回 .handled
,它将阻止子视图接收按键事件。
结论
在 SwiftUI 中检测按键事件允许你侦听特定键或一组键。你可以关注抬起、按下、重复或所有 阶段,并使用处理程序执行任何操作。如果你的视图没有焦点,或者如果父视图侦听按键事件,你可能无法收到任何回调。