Я пытаюсь получить TextFormField, который принимает только отрицательные и положительные числа из 5 цифр.
Следующий код, но он ограничивает только цифры и до 5, но не принимает отрицательный знак.
new TextFormField(
maxLines: 1,
keyboardType: TextInputType.number,
enableSuggestions: false,
inputFormatters: [
LengthLimitingTextInputFormatter(5),
FilteringTextInputFormatter.allow(RegExp(r'-?[0-9]')),
],
onChanged: (val) {},
);
Я пробовал следующее регулярное выражение: "-?[0-9]", но оно не допускает отрицательного знака.





Измените RegExp(r'-?[0-9]') на RegExp(r'^-?[0-9]*'). Это не позволяет вам вводить «-», потому что ваше выражение говорит, что у вас должно быть число, но только «-» делает это недействительным, поэтому средство форматирования не позволяет вам вводить отрицательное значение.
Это должно быть '^-?[0-9]*', чтобы поставить знак в начале входной строки, в противном случае FilteringTextInputFormatter также соответствует повторяющемуся и промежуточному минусу "-", например "--651" или "65-23". "
Вы правы, внес изменения
Проблема с использованием входного фильтра заключается в том, что каждая промежуточная строка также должна соответствовать фильтру. Поскольку ваш фильтр не может соответствовать знаку минус "на пути к" вводу "-3", он не работает.
Это когда вы должны отказаться от использования входных фильтров и вместо этого поместить свою проверку в валидатор, который будет применяться только при проверке и не будет препятствовать вводу промежуточных комбинаций в пути.
Действительно, именно по этой причине не рекомендуется использовать регулярное выражение в случае сопоставления всего ввода, однако оставление логики для validator может привести к плохому UX. Лучше используйте TextInputFormatter.withFunction.
Я не понимаю, как это помогает. Если функция по-прежнему не разрешает использовать голый «-», то вы все равно не сможете ввести «-3». Единственное решение состоит в том, чтобы иметь неблокирующий способ показать «сбой» на — но затем обновить до «ОК» на «-3», и это лучше всего сделать с помощью валидатора.
Я согласен. В предлагаемом решении я включил эту проверку newValue.text == '-', чтобы иметь возможность набирать «-». Действительно, валидатор можно использовать для проверки того, что «-» является «неудачным», а «-3» в порядке, но его также можно реализовать с помощью onChanged: (val) => this.value = int.tryParse(val) ?? 0
Как указано @Randal-Schwartz форматировщики оценивают каждый новый ввод, в результате чего каждая промежуточная строка должна соответствовать фильтру, в том числе при начале ввода отрицательного числа, а один только знак минус «-» не соответствует регулярному выражению.
Кроме того, согласно документам FilteringTextInputFormatter, этот форматтер не следует использовать для шаблонов, предназначенных для сопоставления всей строки (например, с [RegExp], которые содержат позиционные сопоставители (^ или $)).
Использование TextInputFormatter с функцией, которая проверяет, можно ли преобразовать ввод в Int, и в противном случае возвращает предыдущий ввод.
new TextFormField(
maxLines: 1,
keyboardType: TextInputType.number,
enableSuggestions: false,
inputFormatters: [
TextInputFormatter.withFunction((oldV, newV) => onlyIntegersFormatter(oldV, newV, precision: 5)),
],
onChanged: (val) {},
);
static TextEditingValue onlyIntegersFormatter(final TextEditingValue oldValue, final TextEditingValue newValue, {final int? precision}) {
if (newValue.text.isEmpty || newValue.text == '-') {
return newValue;
} else {
// Check if the input can be parsed into an Int and returns the previous input otherwise.
final int? newVal = int.tryParse(newValue.text);
if (newVal == null) {
return oldValue;
} else {
// Check for number of digits.
if (digits != null) {
return math.pow(10, precision) > newVal.abs() ? newValue : oldValue;
}
return newValue;
}
}
};
Если Regex по-прежнему остается решением:
new TextFormField(
maxLines: 1,
keyboardType: TextInputType.number,
enableSuggestions: false,
inputFormatters: [
FilteringTextInputFormatter.allow(RegExp(r'^-?\d{0,5}')),
],
onChanged: (val) {},
);
Объяснение регулярного выражения:
Попробуйте
RegExp(r'-?\d*$')вместо этого? Это соответствует вашим потребностям?