概述

#

要控制 LengthLimitingTextInputFormattermaxLength 的行為,請使用 maxLengthEnforcement 而非已棄用的 maxLengthEnforced

背景

#

maxLengthEnforced 引數曾用於決定文字欄位在達到 maxLength 限制時是截斷輸入值,還是(對於 TextFieldTextFormField)在使用者輸入長度超過 maxLength 時顯示字元計數的警告訊息。

然而,為了輸入 CJK 字元,某些輸入法需要使用者在文字欄位中輸入一系列拉丁字元,然後將這些字元轉換為所需的 CJK 字元(這稱為*文字組合*)。拉丁字元序列通常比生成的 CJK 字元長,因此為文字欄位設定硬性的最大字元限制可能會導致使用者因 maxLength 字元限制而無法正常完成文字組合。

文字組合也被某些輸入法用來指示被高亮顯示的組合區域內的文字正在被積極編輯,即使在輸入拉丁字元時也是如此。例如,Android 上的 Gboard 英文鍵盤(與其他許多 Android 輸入法一樣)會將當前單詞置於一個組合區域中。

為了改善這些場景下的輸入體驗,引入了一個新的三態列舉 MaxLengthEnforcement。其值描述了在使用 LengthLimitingTextInputFormatter 應用活動組合區域時支援的策略。一個使用此列舉的新 maxLengthEnforcement 引數已新增到文字欄位中,以取代布林值 maxLengthEnforced 引數。透過新的列舉引數,開發人員可以根據文字欄位期望的內容型別選擇不同的策略。

有關更多資訊,請參閱 maxLengthMaxLengthEnforcement 的文件。

maxLengthEnforcement 引數的預設值是從應用程式的 TargetPlatform 推斷的,以符合平臺的約定。

變更說明

#
  • 添加了使用新的列舉型別 MaxLengthEnforcementmaxLengthEnforcement 引數,作為 TextFieldTextFormFieldCupertinoTextFieldLengthLimitingTextInputFormatter 類中已棄用的布林值 maxLengthEnforced 引數的替代品。

遷移指南

#

推薦使用當前平臺的預設行為,因為這對於使用者來說是最熟悉的行為。

maxLengthEnforcement 的預設值

#
  • Android、Windows:MaxLengthEnforcement.enforced。這些平臺的原生行為是強制執行的。無論使用者是否在組合輸入,輸入的值都將被截斷。
  • iOS、macOS:MaxLengthEnforcement.truncateAfterCompositionEnds。這些平臺沒有“最大長度”功能,因此要求開發人員自行實現該行為。在這些平臺上似乎沒有出現標準的約定。我們選擇允許組合文字超出最大長度,以避免破壞 CJK 輸入。
  • Web 和 Linux:MaxLengthEnforcement.truncateAfterCompositionEnds。雖然這些平臺沒有標準(並且存在許多行為衝突的實現),但常見的約定似乎是預設允許組合文字超出最大長度。
  • Fuchsia:MaxLengthEnforcement.truncateAfterCompositionEnds。此平臺尚無平臺約定,因此我們選擇預設採用最不可能導致資料丟失的約定。

始終強制執行限制

#

要強制執行當值達到限制時始終截斷的限制(例如,輸入驗證碼時),請在可編輯文字欄位中使用 MaxLengthEnforcement.enforced

當與依賴文字組合的輸入法一起使用時,此選項可能會導致使用者體驗不佳。當文字欄位期望任意使用者輸入(可能包含 CJK 字元)時,請考慮使用 truncateAfterCompositionEnds 選項。有關更多資訊,請參閱 背景 部分。

遷移前的程式碼

dart
TextField(maxLength: 6)

dart
TextField(
  maxLength: 6,
  maxLengthEnforced: true,
)

遷移後的程式碼

dart
TextField(
  maxLength: 6,
  maxLengthEnforcement: MaxLengthEnforcement.enforced,
)

不強制執行限制

#

要在 TextField 中顯示最大長度錯誤,但在超過限制時截斷,請使用 MaxLengthEnforcement.none 而非 maxLengthEnforced: false

遷移前的程式碼

dart
TextField(
  maxLength: 6,
  maxLengthEnforced: false,
)

遷移後的程式碼

dart
TextField(
  maxLength: 6,
  maxLengthEnforcement: MaxLengthEnforcement.none,
)

對於無法顯示錯誤訊息的 CupertinoTextField,只需不設定 maxLength 值。

遷移前的程式碼

dart
CupertinoTextField(
  maxLength: 6,
  maxLengthEnforced: false,
)

遷移後的程式碼

dart
CupertinoTextField()

強制執行限制,但不是針對組合文字

#

為避免在使用者使用組合輸入文字時截斷文字,請指定 MaxLengthEnforcement.truncateAfterCompositionEnds。此行為允許使用組合區域大於最終文字的輸入法(例如,中文、日文和韓文(CJK)文字很常見)暫時忽略限制,直到編輯完成。

Android 上的 Gboard 英文鍵盤(以及許多其他 Android 輸入法)會為正在輸入的單詞建立一個組合區域。當在 truncateAfterCompositionEnds 文字欄位中使用時,使用者不會在 maxLength 限制處立即停止。如果您確信文字欄位不會與使用暫時性長組合區域(如 CJK 文字)的輸入法一起使用,請考慮 enforced 選項。

實現程式碼

dart
TextField(
  maxLength: 6,
  maxLengthEnforcement: MaxLengthEnforcement.truncateAfterCompositionEnds, // Temporarily lifts the limit.
)

請注意,不要假設輸入不會使用組合區域

#

當針對特定區域設定時,人們很容易認為所有使用者都會滿意於該區域的輸入。例如,針對英語社群的論壇軟體可能會被假定為只需要處理英語文字。然而,這種假設通常是錯誤的。例如,也許英語論壇的參與者想討論日本動漫或越南菜。也許其中一位參與者是韓國人,更喜歡用他們的母語表意文字來表達名字。因此,自由格式欄位應很少使用 enforced 值,而應儘可能優先使用 truncateAfterCompositionEnds 值。

時間線

#

已在版本:v1.26.0-1.0.pre 中釋出
穩定版本:2.0.0

參考資料

#

設計文件

API 文件

相關問題

相關 PR

  • PR 63754: 修復 TextField 在組合和 maxLength 設定時崩潰的問題
  • PR 68086: 引入 MaxLengthEnforcement