Skip to main content

TextField FocusNode 附加位置變更

EditableText.focusNode 不再附加於 EditableTextState 的 BuildContext。

摘要

#

EditableText.focusNode 現在會附加到 EditableText 下方的一個專用 Focus 元件 (Widget)。

背景說明

#

一個文字輸入欄位元件(例如 TextField) 通常會擁有一個 FocusNode。 當該 FocusNode 是應用程式的主要焦點時, 事件(例如鍵盤按鍵)會被傳送到 FocusNode 所附加的 BuildContext

FocusNode 也在快捷鍵處理中扮演角色: Shortcuts 元件會將按鍵序列轉換為 Intent, 並嘗試從附加了 FocusNodeBuildContext 開始,往元件樹(Widget tree)根部尋找第一個適合該 Intent 的處理器。 這代表如果一個 Actions 元件(提供不同 Intent 的處理器) 位於樹狀結構下方,當主要焦點的 BuildContext 位於其上方時, 將無法處理任何快捷鍵 Intent

過去在 EditableText 中,FocusNode 會附加於 EditableTextStateBuildContext。 任何在 EditableTextState 中定義的 Actions 元件(這些元件會被插入在 EditableTextStateBuildContext 下方) 即使該 EditableText 已獲得焦點,也無法處理快捷鍵, 原因如上所述。

變更說明

#

EditableTextState 現在會建立一個專用的 Focus 元件來 承載 EditableText.focusNode。 這讓 EditableTextState 可以為快捷鍵 Intent 定義處理器。 例如,EditableText 現在有一個處理器, 當按下 DEL 鍵時,會處理 "deleteCharacter" intent。

這項變更不涉及任何公開 API 變更, 但會影響依賴該特定實作細節來判斷 FocusNode 是否與文字輸入欄位相關聯的程式碼庫。

這項變更不會導致建置失敗,但可能會在執行時產生問題, 或導致現有測試失敗。

遷移指南

#

EditableText 元件(Widget)會以 FocusNode 作為參數, 過去這個參數會附加到其 EditableTextBuildContext。 如果你依賴於執行時型別檢查來判斷 FocusNode 是否附加於文字輸入欄位或可選取文字欄位,例如:

  • focusNode.context.widget is EditableText
  • (focusNode.context as StatefulElement).state as EditableTextState

請繼續閱讀,並考慮依照下方遷移步驟操作,以避免破壞。

如果你不確定程式碼庫是否需要遷移, 請搜尋 is EditableTextas EditableTextis EditableTextStateas EditableTextState,並確認搜尋結果中是否有對 FocusNode.context 進行型別檢查或型別轉換的情況。 如果有,則需要進行遷移。

為了避免對 FocusNode 關聯的 BuildContext 進行型別檢查或向下轉型, 並根據程式碼庫實際想從該 FocusNode 呼叫的功能, 請從該 BuildContext 觸發一個 Intent。 例如,如果你想將目前獲得焦點的 TextField 文字更新為特定值,請參考下方範例:

遷移前的程式碼:

dart
final Widget? focusedWidget = primaryFocus?.context?.widget;
if (focusedWidget is EditableText) {
  widget.controller.text = 'Updated Text';
}

遷移後的程式碼:

dart
final BuildContext? focusedContext = primaryFocus?.context;
if (focusedContext != null) {
  Actions.maybeInvoke(focusedContext, ReplaceTextIntent('UpdatedText'));
}

如需 EditableText 元件所支援的 Intent 完整清單, 請參閱 EditableText 元件的文件。

時程

#

合併於版本:2.6.0-12.0.pre
進入穩定版:2.10.0

參考資料

#

API 文件:

相關 PR: