2020-11-18 解决Flutter TextField限制输入中文问题

项目中存在一个输入框,只能提交中文字符串,于是使用了如下的方法实现

            TextField(
              /// 输入文本格式过滤
              inputFormatters: [
                /// 输入的内容长度为 10 位
                LengthLimitingTextInputFormatter(10),

                /// 只能输入汉字或者字母或数字
                WhitelistingTextInputFormatter(
                  RegExp("[a-zA-Z]|[\u4e00-\u9fa5]|[0-9]"),
                ),
              ],
            ),

但是上线运行之后,发现在iOS原生拼音输入法中,只能一个字一个字输入,每次输入超过一个字就会直接变成拼音字母,并且长度限制在遇到中文拼音输入法后也会失效

有问题的输入框.gif

于是通过自定义过滤器的方法,解决了这个问题

            TextField(
              inputFormatters: [
                /// 输入的内容长度为 10 位
                CustomizedLengthTextInputFormatter(10),

                /// 只能输入汉字或者字母或数字
                CustomizedTextInputFormatter(
                  filterPattern: RegExp("[a-zA-Z]|[\u4e00-\u9fa5]|[0-9]"),
                ),
              ],
            ),
修复后的输入框.gif
/// 自定义兼容中文拼音输入法正则校验输入框
class CustomizedTextInputFormatter extends TextInputFormatter {
  final Pattern filterPattern;

  CustomizedTextInputFormatter({this.filterPattern})
      : assert(filterPattern != null);

  @override
  TextEditingValue formatEditUpdate(
    TextEditingValue oldValue,
    TextEditingValue newValue,
  ) {
    if (newValue.isComposingRangeValid) return newValue;
    return FilteringTextInputFormatter.allow(filterPattern)
        .formatEditUpdate(oldValue, newValue);
  }
}

/// 自定义兼容中文拼音输入法长度限制输入框
class CustomizedLengthTextInputFormatter extends TextInputFormatter {
  final int maxLength;

  CustomizedLengthTextInputFormatter(this.maxLength);

  @override
  TextEditingValue formatEditUpdate(
    TextEditingValue oldValue,
    TextEditingValue newValue,
  ) {
    if (newValue.isComposingRangeValid) return newValue;
    return LengthLimitingTextInputFormatter(maxLength)
        .formatEditUpdate(oldValue, newValue);
  }
}

关键方法在于判断当前输入框是否存在未完成的字符串,如果存在,则不做限制,否则根据参数进行限制

  /// Whether the [composing] range is a valid range within [text].
  ///
  /// Returns true if and only if the [composing] range is normalized, its start
  /// is greater than or equal to 0, and its end is less than or equal to
  /// [text]'s length.
  ///
  /// If this property is false while the [composing] range's `isValid` is true,
  /// it usually indicates the current [composing] range is invalid because of a
  /// programming error.
  bool get isComposingRangeValid => composing.isValid && composing.isNormalized && composing.end <= text.length;

但是属性 composing 听说还存在bug,使用的时候要注意,很有可能还有坑等着

参考:
https://blog.csdn.net/NNadn/article/details/90673361
https://blog.csdn.net/qq_27494201/article/details/106638855

解决方案:
https://juejin.im/post/6886279718543294478
https://github.com/flutter/flutter/pull/69553

顿悟:
https://github.com/AlexV525

感谢 Alex 大神!!!

你可能感兴趣的:(2020-11-18 解决Flutter TextField限制输入中文问题)