日期的颤动文本字段输入验证 [英] Flutter TextField input validation for a date

查看:25
本文介绍了日期的颤动文本字段输入验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写一个日期输入控件,它接受类似于23/12/1997的日期。我希望它自动为用户插入/字符。因此,当他们键入23时,监听器返回23/,这样他们就可以键入12。此时,监听器再次添加一个/,让用户通过键入1997来完成日期。 我的TextEditingController代码工作正常,如下所示:

final _controller = TextEditingController();
_controller.addListener(() {
      String text = _controller.text;
      if (text.length == 2) {
        text += '/';
      }
      if (text.length == 5) {
        text += '/';
      }
      _controller.value = _controller.value.copyWith(
        text: text,
        selection:
            TextSelection(baseOffset: text.length, extentOffset: text.length),
        composing: TextRange.empty,
      );
      print(_controller.text);
    }

所以它工作得很好,直到用户犯了错误并需要回溯。一旦/被删除,它立即被替换,停止对该日期的任何进一步编辑。

为了使其正常工作,我需要访问以前输入的文本,以确定用户是否使用了退格键。因此,如果text == 23/ && previous_text == 23/1,我可以从文本中删除/。

我发现了这个问题textfield must only accept numbers,我认为它可能会对我有所帮助,但我不确定如何实现现有的小部件并覆盖其方法。当然,在TextEditingController中可能有一种更简单的方法来实现这一点?

推荐答案

我已找到解决日期验证输入所需的内容。它并不完美,但对于我正在努力做的事情来说,它已经足够好了。我所需要的就是查看TextField()的inputForMatters方法。这允许对输入文本进行操作,以将其转换为任意数量的用户定义格式。我为任何想要尝试它的人提供了我的一段代码:

  class _DateFormatter extends TextInputFormatter {
  @override
  TextEditingValue formatEditUpdate(
      TextEditingValue prevText, TextEditingValue currText) {
    int selectionIndex;

    // Get the previous and current input strings
    String pText = prevText.text;
    String cText = currText.text;
    // Abbreviate lengths
    int cLen = cText.length;
    int pLen = pText.length;

    if (cLen == 1) {
      // Can only be 0, 1, 2 or 3
      if (int.parse(cText) > 3) {
        // Remove char
        cText = '';
      }
    } else if (cLen == 2 && pLen == 1) {
      // Days cannot be greater than 31
      int dd = int.parse(cText.substring(0, 2));
      if (dd == 0 || dd > 31) {
        // Remove char
        cText = cText.substring(0, 1);
      } else {
        // Add a / char
        cText += '/';
      }
    } else if (cLen == 4) {
      // Can only be 0 or 1
      if (int.parse(cText.substring(3, 4)) > 1) {
        // Remove char
        cText = cText.substring(0, 3);
      }
    } else if (cLen == 5 && pLen == 4) {
      // Month cannot be greater than 12
      int mm = int.parse(cText.substring(3, 5));
      if (mm == 0 || mm > 12) {
        // Remove char
        cText = cText.substring(0, 4);
      } else {
        // Add a / char
        cText += '/';
      }
    } else if ((cLen == 3 && pLen == 4) || (cLen == 6 && pLen == 7)) {
      // Remove / char
      cText = cText.substring(0, cText.length - 1);
    } else if (cLen == 3 && pLen == 2) {
      if (int.parse(cText.substring(2, 3)) > 1) {
        // Replace char
        cText = cText.substring(0, 2) + '/';
      } else {
        // Insert / char
        cText =
            cText.substring(0, pLen) + '/' + cText.substring(pLen, pLen + 1);
      }
    } else if (cLen == 6 && pLen == 5) {
      // Can only be 1 or 2 - if so insert a / char
      int y1 = int.parse(cText.substring(5, 6));
      if (y1 < 1 || y1 > 2) {
        // Replace char
        cText = cText.substring(0, 5) + '/';
      } else {
        // Insert / char
        cText = cText.substring(0, 5) + '/' + cText.substring(5, 6);
      }
    } else if (cLen == 7) {
      // Can only be 1 or 2
      int y1 = int.parse(cText.substring(6, 7));
      if (y1 < 1 || y1 > 2) {
        // Remove char
        cText = cText.substring(0, 6);
      }
    } else if (cLen == 8) {
      // Can only be 19 or 20
      int y2 = int.parse(cText.substring(6, 8));
      if (y2 < 19 || y2 > 20) {
        // Remove char
        cText = cText.substring(0, 7);
      }
    }

    selectionIndex = cText.length;
    return TextEditingValue(
      text: cText,
      selection: TextSelection.collapsed(offset: selectionIndex),
    );
  }
}

要使用它,只需从Textfield()调用它,如下所示。我还合并了两个内置方法。如果为WhitelistingTextInputFormatter(),则只允许输入数字和斜杠(/)字符;如果为LengthLimitingTextInputFormatter(),则限制允许的字符数。后者可以使用TextField()的max Length参数来实现,但这里仅作为示例。请注意,还有一个BlacklistingTextInputFormatter(),其功能与您预期的不谋而合。

WhitelistingTextInputFormatter已被删除,请使用FilteringTextInputFormatter.allow(RegExp(";[0-9-]";)),替换,如果您要更改拆分符号(当前为/&q;),请将其添加到RegExp(...)

TextField(
  // maxLength: 10,
  keyboardType: TextInputType.datetime,
  controller: _controllerDOB,
  focusNode: _focusNodeDOB,
  decoration: InputDecoration(
    hintText: 'DD/MM/YYYY',
    counterText: '',
  ),
  inputFormatters: [
    WhitelistingTextInputFormatter(RegExp("[0-9/]")),
    LengthLimitingTextInputFormatter(10),
    _DateFormatter(),
  ],
),

这篇关于日期的颤动文本字段输入验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆