Skip to main content

將 ShortcutActivator 與 ShortcutManager 遷移至 KeyEvent 系統

原始鍵盤事件子系統已被鍵盤事件子系統取代, 所有使用 RawKeyEvent 與 RawKeyboard 的 API 已轉換為 KeyEvent 與 HardwareKeyboard。

摘要

#

Flutter 已經同時實作了兩套鍵盤事件(key events)系統有一段時間(數年)。新的系統已經與舊的、平台特定的原始鍵盤事件系統達到功能等同,且原始系統即將被移除。為了迎接這個變化,所有使用舊系統的 Flutter API 正在進行修改,並且對於其中少數 API,我們決定進行破壞性更動,以維持 API 的品質。

背景

#

在原始的鍵盤事件子系統中,為了處理各平台的特殊行為,無論是在框架還是用戶端應用程式,都導致了過於複雜的程式碼,而且舊系統無法正確反映系統上鍵盤事件的實際狀態。

因此,新的 KeyEvent-為基礎的系統誕生了。為了將破壞性更動降到最低,新的系統與舊系統並行實作,最終目標是淘汰原始系統。這個時機很快就會到來,為了準備,我們已經針對 API 品質進行了必要的最小破壞性更動。

變更說明

#

受影響的 API 摘要如下:

  • ShortcutActivator.accepts 現在接收 KeyEvent 與 HardwareKeyboard。
  • ShortcutActivator.isActivatedBy 現已棄用。請直接呼叫 accepts。
  • ShortcutActivator.triggers 現在為選填,若未實作則回傳 null。
  • ShortcutManager.handleKeypress 現在接收 KeyEvent。

這項變更將 ShortcutActivator.accepts 方法修改為接收 KeyEvent 與 HardwareKeyboard,取代先前的 RawKeyEvent 與 RawKeyboard。

ShortcutActivator.accepts 的意義有些微調整。在此變更前,假設只有當 ShortcutActivator.triggers 回傳 null 時, 或傳給 accepts 的鍵盤事件(key event)具有在 triggers 清單中的 logical key 時,才會呼叫 accepts。現在則會無條件呼叫,且可選擇性地利用 triggers 清單提升效能,但並非強制。Flutter 的子類別如 SingleActivator 與 CharacterActivator 已經這麼做。

這項變更也將 ShortcutManager.handleKeypress 方法修改為接收 KeyEvent,取代先前的 RawKeyEvent。

遷移指南

#

Flutter 框架所提供的 API 已經完成遷移。只有當你使用上一節所列方法時,才需要進行遷移。

遷移你使用 ShortcutActivator 或其子類別的 API

#

請傳遞 KeyEvent,而非 RawKeyEvent 給 ShortcutActivator.accepts。 這可能意味著你需要調整取得鍵盤事件(key events)的方式。根據你取得事件的來源,可能需要從 Focus.onKey 切換為 Focus.onKeyEvent,或是如果你使用 FocusScope、FocusNode 或 FocusScopeNode,則進行類似的調整。

如果你使用的是 RawKeyboardListener,請改用 KeyboardListener。如果你直接存取 RawKeyboard,請改用 HardwareKeyboard。你會發現所有鍵盤事件來源都有非 raw 版本可用。

遷移你擴充 ShortcutActivator 的 API

#

ShortcutActivator.accepts 方法已修改為接收 KeyEvent 與 HardwareKeyboard,取代先前的 RawKeyEvent 與 RawKeyboard。

變更前:

dart
class MyActivator extends ShortcutActivator {
  @override
  bool accepts(RawKeyEvent event, RawKeyboard state) {
    // ... (your implementation here)
    returns false;
  }
  // ...
}

變更後:

dart
class MyActivator extends ShortcutActivator {
  @override
  bool accepts(KeyEvent event, HardwareKeyboard state) {
    // ... (your implementation here)
    returns false;
  }
  // ...
}

遷移擴充 ShortcutManager 的 API

#

ShortcutManager 類別已修改為在 handleKeypress 中接收 KeyEvent,而非 RawKeyEvent。這兩個 API 之間有一個差異:重複鍵的判斷方式不同。在 RawKeyEvent 的情況下,repeat 成員用於表示重複,但在 KeyEvent 的程式碼中,事件會是另一種型別(KeyRepeatEvent)。

變更前:

dart
class _MyShortcutManager extends ShortcutManager {
  @override
  KeyEventResult handleKeypress(BuildContext context, RawKeyEvent event) {
    if (event is! RawKeyDownEvent) {
      return KeyEventResult.ignored;
    }
    if (event.repeat) {
      // (Do something with repeated keys.)
    }
    // ... (your implementation here)
    return KeyEventResult.handled;
  }
}

變更後:

dart
class _MyShortcutManager extends ShortcutManager {
  @override
  KeyEventResult handleKeypress(BuildContext context, KeyEvent event) {
    if (event is! KeyDownEvent && event is! KeyRepeatEvent) {
      return KeyEventResult.ignored;
    }
    if (event is KeyRepeatEvent) {
      // (Do something with repeated keys.)
    }
    // ... (your implementation here)
    return KeyEventResult.handled;
  }
}

時程

#

合併於版本:3.17.0-5.0.pre
正式版釋出於:3.19.0

參考資料

#

API 文件:

相關議題:

相關 PR: