如何在Flutter中实现文本掩码

9

如标题所述,如何在Flutter中实现文本掩码。

我只写了一个示例,但不是很适合,因为当用户输入时无法向用户显示掩码。例如,当文本掩码为'MM/HH'时,在用户输入期间如果我们不显示斜杠'/',用户将会自己输入斜杠'/',因为他们不知道斜杠将自动填充输入。这里有一个示例可以解释我的意思(这是一个Web实现,而不是Flutter),那么如何在Flutter中实现与此链接类似的掩码?

这是我的当前实现。

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class MaskedTextInputFormatter extends TextInputFormatter {
  final String mask;
  final String separator;

  MaskedTextInputFormatter({
    @required this.mask,
    @required this.separator,
  }) {
    assert(mask != null);
    assert(separator != null);
  }

  @override
  TextEditingValue formatEditUpdate(
      TextEditingValue oldValue, TextEditingValue newValue) {
    if (newValue.text.length > 0) {
      if (newValue.text.length > oldValue.text.length) {
        if (newValue.text.length > mask.length) return oldValue;
        if (newValue.text.length < mask.length &&
            mask[newValue.text.length - 1] == separator) {
          return TextEditingValue(
            text:
                '${oldValue.text}$separator${newValue.text.substring(newValue.text.length - 1)}',
            selection: TextSelection.collapsed(
              offset: newValue.selection.end + 1,
            ),
          );
        }
      }
    }
    return newValue;
  }
}

希望能得到任何帮助!

PS:我搜索了一个名为mask_text_input_formatter的Flutter包,似乎在输入时也无法显示掩码,请参见问题

1个回答

1
尝试通过添加额外条件来修改文本值。
  1. add 1 extra condition.

    import 'package:flutter/material.dart';
    import 'package:flutter/services.dart';
    
    class MaskedTextInputFormatter extends TextInputFormatter {
      final String mask;
      final String separator;
    
      MaskedTextInputFormatter({
        @required this.mask,
        @required this.separator,
      }) {
        assert(mask != null);
        assert(separator != null);
      }
    
      @override
      TextEditingValue formatEditUpdate(
          TextEditingValue oldValue, TextEditingValue newValue) {
        if (newValue.text.length > 0) {
          if (newValue.text.length > oldValue.text.length) {
            if (newValue.text.length > mask.length) return oldValue;
            if (newValue.text.length < mask.length &&
                mask[newValue.text.length - 1] == separator &&
                newValue.text.substring(newValue.text.length - 1) != separator) {
              return TextEditingValue(
                text:
                    '${oldValue.text}$separator${newValue.text.substring(newValue.text.length - 1)}',
                selection: TextSelection.collapsed(
                  offset: newValue.selection.end + 1,
                ),
              );
            }
          }
        }
        return newValue;
      }
    }

  2. by using regex depending your need.

      FilteringTextInputFormatter(r"[A-za-z][A-Za-z]\/[A-za-z][A-Za-z]", allow: false);
    

或者

     FilteringTextInputFormatter(r"[A-za-z0-9][A-Za-z0-9]\/[A-za-z0-9][A-Za-z0-9]", allow: false);

以下是示例:allow参数用于控制是否允许特定的模式被接受。

Textfield(
  label: "CardNumber",
  hint: "CardNumber",
  focusNode: cardNumberFocus,
  textInputFormatter: [
    MaskedTextInputFormatter(mask: 'xxxx xxxx xxxx xxxx', separator: ' '),
    FilteringTextInputFormatter(r"[A-za-z0-9][A-Za-z0-9]\/[A-za-z0-9][A-Za-z0-9]", allow: true);
  ],
);

谢谢您的回答!但我仍然不明白allow参数的含义是什么?FilteringTextInputFormatter又是什么? - Kevin Zhang
FilteringTextInputFormatter是用于文本字段的内置格式化程序,在其中您必须将allow参数传递为true/false。 - kishan vekariya
使用您更新后的答案,我无法在文本字段中输入任何字符,似乎它会防止所有字符。 - Kevin Zhang
嗨,kishan vekariya,你能帮忙在https://dartpad.dev/上做一个最小的示例吗? - Kevin Zhang
请查看此处的CodePen示例:https://codepen.io/kishan-sa/pen/YzZgZxx - kishan vekariya
1
无论如何,感谢您的回答,但这不是我想要的。我想要的是:一旦用户开始输入,分隔符应该显示出来,以引导用户输入。就像 https://text-mask.github.io/text-mask/ 中的 guide 参数一样。 - Kevin Zhang

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接