将 RawKeyEvent/RawKeyboard 系统迁移到 KeyEvent/HardwareKeyboard 系统
摘要
#一段时间以来(几年),Flutter 实现了两个关键事件系统。新系统与旧的平台特定原始键盘事件系统实现了功能对等,并且原始系统已被弃用。
上下文
#在原始键盘事件子系统中,处理框架和客户端应用中每个平台的特性导致代码过于复杂,并且旧系统没有正确表示系统上键盘事件的真实状态。
旧版 API RawKeyboard
已被弃用,将在未来移除。 HardwareKeyboard
和 KeyEvent
API 替换了此旧版 API。此更改的一个示例是 FocusNode.onKeyEvent
替换了 FocusNode.onKey
。
RawKeyboard
的行为提供的事件模型不如 HardwareKeyboard
提供的统一和规则。请考虑以下示例
- 按下事件并不总是与弹起事件匹配,反之亦然(已按下键的集合被静默更新)。
- 按下事件的逻辑键并不总是与弹起事件的逻辑键相同。
- 按下事件和重复事件不容易区分(必须手动跟踪)。
- 锁定模式(如 CapsLock)仅记录其“启用”状态。无法获取其按下状态。
因此,新的基于 KeyEvent
/HardwareKeyboard
的系统诞生了,为了最大程度地减少重大更改,它与旧系统并行实现,目的是最终弃用原始系统。现在是时候了,应用程序开发人员应该迁移其代码以避免在移除已弃用 API 时发生的重大更改。
更改说明
#以下是已弃用的 API。
具有等效替代的已弃用 API
#Focus.onKey
=>Focus.onKeyEvent
FocusNode.attach
的onKey
参数 =>onKeyEvent
参数FocusNode.onKey
=>FocusNode.onKeyEvent
FocusOnKeyCallback
=>FocusOnKeyEventCallback
FocusScope.onKey
=>FocusScope.onKeyEvent
FocusScopeNode.onKey
=>FocusScopeNode.onKeyEvent
RawKeyboard
=>HardwareKeyboard
RawKeyboardListener
=>KeyboardListener
RawKeyDownEvent
=>KeyDownEvent
RawKeyEvent
=>KeyEvent
RawKeyUpEvent
=>KeyUpEvent
已停止使用的 API
#当只有一个键盘事件系统时,不再需要这些 API,或者不再提供其功能。
debugKeyEventSimulatorTransitModeOverride
GLFWKeyHelper
GtkKeyHelper
KeyboardSide
KeyDataTransitMode
KeyEventManager
KeyHelper
KeyMessage
KeyMessageHandler
KeySimulatorTransitModeVariant
ModifierKey
RawKeyEventData
RawKeyEventDataAndroid
RawKeyEventDataFuchsia
RawKeyEventDataIos
RawKeyEventDataLinux
RawKeyEventDataMacOs
RawKeyEventDataWeb
RawKeyEventDataWindows
RawKeyEventHandler
ServicesBinding.keyEventManager
迁移指南
#Flutter 框架库已完成迁移。如果您的代码使用了上一节中列出的任何类或方法,请迁移到这些新的 API。
迁移使用 RawKeyEvent
的代码
#在大多数情况下,所有 RawKeyEvent
API 都提供了等效的 KeyEvent
API。
一些与 RawKeyEventData
对象或其子类中包含的平台特定信息相关的 API 已被移除,不再受支持。一个例外是 RawKeyEventDataAndroid.eventSource
信息现在可以作为 KeyEvent.deviceType
以更独立于平台的形式访问。
迁移 isKeyPressed
和相关函数
#如果旧版代码使用了 RawKeyEvent.isKeyPressed
、RawKeyEvent.isControlPressed
、RawKeyEvent.isShiftPressed
、RawKeyEvent.isAltPressed
或 RawKeyEvent.isMetaPressed
API,现在 HardwareKeyboard
单例实例上提供了等效函数,但在 [KeyEvent] 上不可用。 RawKeyEvent.isKeyPressed
可作为 HardwareKeyboard.isLogicalKeyPressed
使用。
之前
KeyEventResult _handleKeyEvent(RawKeyEvent keyEvent) {
if (keyEvent.isControlPressed ||
keyEvent.isShiftPressed ||
keyEvent.isAltPressed ||
keyEvent.isMetaPressed) {
print('Modifier pressed: $keyEvent');
}
if (keyEvent.isKeyPressed(LogicalKeyboardKey.keyA)) {
print('Key A pressed.');
}
return KeyEventResult.ignored;
}
之后
KeyEventResult _handleKeyEvent(KeyEvent _) {
if (HardwareKeyboard.instance.isControlPressed ||
HardwareKeyboard.instance.isShiftPressed ||
HardwareKeyboard.instance.isAltPressed ||
HardwareKeyboard.instance.isMetaPressed) {
print('Modifier pressed: $keyEvent');
}
if (HardwareKeyboard.instance.isLogicalKeyPressed(LogicalKeyboardKey.keyA)) {
print('Key A pressed.');
}
return KeyEventResult.ignored;
}
为焦点设置 onKey
#如果旧版代码使用了 Focus.onKey
、FocusScope.onKey
、FocusNode.onKey
或 FocusScopeNode.onKey
参数,则存在等效的 Focus.onKeyEvent
、FocusScope.onKeyEvent
、FocusNode.onKeyEvent
或 FocusScopeNode.onKeyEvent
参数,它提供 KeyEvent
而不是 RawKeyEvent
。
之前
Widget build(BuildContext context) {
return Focus(
onKey: (RawKeyEvent keyEvent) {
print('Key event: $keyEvent');
return KeyEventResult.ignored;
}
child: child,
);
}
之后
Widget build(BuildContext context) {
return Focus(
onKeyEvent: (KeyEvent keyEvent) {
print('Key event: $keyEvent');
return KeyEventResult.ignored;
}
child: child,
);
}
重复键盘事件处理
#如果您依赖 RawKeyEvent.repeat
属性来确定键是否为重复的键盘事件,该属性现已分离到单独的 KeyRepeatEvent
类型中。
之前
KeyEventResult _handleKeyEvent(RawKeyEvent keyEvent) {
if (keyEvent is RawKeyDownEvent) {
print('Key down: ${keyEvent.data.logicalKey.keyLabel}(${keyEvent.repeat ? ' (repeated)' : ''})');
}
return KeyEventResult.ignored;
}
之后
KeyEventResult _handleKeyEvent(KeyEvent _) {
if (keyEvent is KeyDownEvent || keyEvent is KeyRepeatEvent) {
print('Key down: ${keyEvent.logicalKey.keyLabel}(${keyEvent is KeyRepeatEvent ? ' (repeated)' : ''})');
}
return KeyEventResult.ignored;
}
虽然它不是 KeyDownEvent
的子类,但 KeyRepeatEvent
也是一个键盘按下事件。不要假设 keyEvent is! KeyDownEvent
仅允许键盘弹起事件。检查 KeyDownEvent
和 KeyRepeatEvent
。
时间线
#包含版本:3.18.0-7.0.pre
稳定版:3.19.0
参考
#替换 API 文档
Focus.onKeyEvent
FocusNode.onKeyEvent
FocusOnKeyEventCallback
FocusScope.onKeyEvent
FocusScopeNode.onKeyEvent
HardwareKeyboard
KeyboardListener
KeyDownEvent
KeyRepeatEvent
KeyEvent
KeyEventHandler
KeyUpEvent
相关问题
相关 PR
除非另有说明,否则本网站上的文档反映了 Flutter 的最新稳定版本。页面上次更新于 2024-04-04。 查看源代码 或 报告问题.