Проверка ввода Flutter TextField для даты - PullRequest
0 голосов
/ 19 июня 2020

Я пытаюсь написать элемент управления вводом даты, который принимает дату, например, 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, я могу удалить / из текста.

Я нашел этот вопрос текстовое поле должно принимать только числа , и я думаю, что это может мне помочь, но я не уверен, как реализовать существующий виджет и переопределить его методы. Конечно, может быть более простой способ сделать это в TextEditingController?

Ответы [ 2 ]

1 голос
/ 10 июля 2020

Я нашел то, что мне нужно, чтобы разрешить ввод проверки даты. Это не идеально, но достаточно для того, что я пытаюсь сделать. Все, что мне нужно было, это взглянуть на метод inputFormatters TextField (). Это позволяет манипулировать входным текстом, чтобы поместить его в любое количество пользовательских форматов. Я включаю фрагмент своего кода для всех, кто хотел бы попробовать его:

  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 () , чтобы можно было вводить только цифры и символ sla sh (/), и LengthLimitingTextInputFormatter () , чтобы ограничить количество разрешенных символов. Последнее может быть достигнуто с помощью параметра maxLength TextField (), но это здесь в качестве примера. Обратите внимание, что существует также BlacklistingTextInputFormatter () , который работает так, как вы ожидаете.

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(),
  ],
),
0 голосов
/ 19 июня 2020

Вы можете использовать диалог выбора даты, созданный с помощью flutter.

DateTime _date = DateTime.now()


onPressed: () {
  showDatePicker(
    context: context,
    initialDate: _date,
    firstDate: DateTime(2020),
    lastDate: DateTime(2021),
    ).then((date) {
      setState(() {
    _date = date;
    });
  });
},
...