將 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 framework 函式庫已完成遷移。如果您的程式碼使用上一節列出的任何類別或方法,請遷移至這些新的 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。 檢視來源 或 回報問題。