跳至主要内容

使用 maxLengthEnforcement 替换 maxLengthEnforced

摘要

#

要控制LengthLimitingTextInputFormattermaxLength的行为,请使用maxLengthEnforcement代替现已弃用的maxLengthEnforced

上下文

#

maxLengthEnforced参数用于确定当输入值达到maxLength限制时,文本字段是否应该截断输入值,或者(对于TextFieldTextFormField)是否应该在字符计数中显示警告消息,当用户输入的长度超过maxLength时。

但是,要输入 CJK 字符,一些输入法需要用户在文本字段中输入一系列拉丁字符,然后将此序列转换为所需的 CJK 字符(称为文本合成)。拉丁字符序列通常比生成的 CJK 字符更长,因此在文本字段上设置硬性最大字符限制可能意味着用户无法正常完成文本合成,因为maxLength字符限制。

文本合成也被一些输入法用来表示突出显示的合成区域内的文本正在被积极编辑,即使在输入拉丁字符时也是如此。例如,Android 上的 Gboard 英语键盘(与 Android 上许多其他输入法一样)将当前单词放在合成区域中。

为了改善这些场景下的输入体验,引入了一个新的三态枚举MaxLengthEnforcement。它的值描述了在应用LengthLimitingTextInputFormatter时处理活动合成区域的支持策略。一个使用此枚举的新maxLengthEnforcement参数已添加到文本字段中,以替换布尔型maxLengthEnforced参数。使用新的枚举参数,开发人员可以根据文本字段期望的内容类型选择不同的策略。

有关更多信息,请参阅maxLengthMaxLengthEnforcement的文档。

maxLengthEnforcement参数的默认值是从应用程序的TargetPlatform推断出来的,以符合平台的约定。

更改说明

#
  • 添加了一个使用新枚举类型MaxLengthEnforcementmaxLengthEnforcement参数,以替换现已弃用的布尔型maxLengthEnforced参数,该参数位于TextFieldTextFormFieldCupertinoTextFieldLengthLimitingTextInputFormatter类上。

迁移指南

#

建议使用当前平台的默认行为,因为这将是用户最熟悉的行为。

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