Flutter의 TextField
위젯에서 입력을 받다보면, 정규식을 이용해야 할 때가 온다.
TextField(
inputFormatters: [
FilteringTextInputFormatter.deny(RegExp(r'[/\\]')),
],
)
검색을 하다보면, 늘 그렇듯이 내가 원하는 입맛에 딱 맞는 코드는 안나오는게 국룰.
이 글을 보는 독자들도 딱 입맛에 맞는 것은 아니겠지만, 최대한 큰 틀에서 설명 해보고자 한다.
우선 TextField
위젯 안에는 inputFormatters
라는 파라미터가 있다.
final List<TextInputFormatter>? inputFormatters;
TextInputFormatter
는 abstract 클래스로 구성되어있다.
abstract class TextInputFormatter {
/// Called when text is being typed or cut/copy/pasted in the [EditableText].
///
/// You can override the resulting text based on the previous text value and
/// the incoming new text value.
///
/// When formatters are chained, `oldValue` reflects the initial value of
/// [TextEditingValue] at the beginning of the chain.
TextEditingValue formatEditUpdate(
TextEditingValue oldValue,
TextEditingValue newValue,
);
그래서 ㅇㅉㄹㄱ,,,
그러니까, TextInputFormatter를 참조하는 FilteringTextInputFormatter
클래스가 있다.
FilteringTextInputFormatter(
this.filterPattern, {
required this.allow,
this.replacementString = '',
}) : assert(filterPattern != null),
assert(allow != null),
assert(replacementString != null);
따라서, FilteringTextInputFormatter
를 사용하면 된다.
- FilteringTextInputFormatter.digitsOnly
- FilteringTextInputFormatter.allow(RegExp(r'[0-9]'))
Full Code
TextFormField(
keyboardType: TextInputType.number,
inputFormatters: [
FilteringTextInputFormatter.digitsOnly
],
),
또는
TextFormField(
keyboardType: TextInputType.number,
inputFormatters: [
FilteringTextInputFormatter.allow(RegExp(r'[0-9]'))
],
),
이런식으로 사용할 수 있다.
final inputFormatter = FilteringTextInputFormatter.allow(RegExp(r'^[1-9]{1}.{0,5}'));
class UnitInputFormatter extends TextInputFormatter {
UnitInputFormatter(this.unit);
final Unit unit;
static const separator = ',';
TextEditingValue formatEditUpdate(
TextEditingValue oldValue, TextEditingValue newValue) {
String oldValueText = oldValue.text.replaceAll(separator, '');
String newValueText = newValue.text.replaceAll(separator, '');
if (newValue.selection.baseOffset == 0) {
return newValue;
}
if (oldValue.text.endsWith(separator) &&
oldValue.text.length == newValue.text.length + 1) {
newValueText = newValueText.substring(0, newValueText.length - 1);
}
// Only process if the old value and new value are different
if (oldValueText != newValueText) {
int selectionIndex =
newValue.text.length - newValue.selection.extentOffset;
final chars = newValueText.split('');
String newString = '';
for (int i = chars.length - 1; i >= 0; i--) {
if ((chars.length - 1 - i) % 3 == 0 && i != chars.length - 1)
newString = separator + newString;
newString = chars[i] + newString;
}
return TextEditingValue(
text: newString.toString() + unit.enumToString(),
selection: TextSelection.collapsed(
offset: newString.length - selectionIndex,
),
);
}
1번 변수를 만들고, 2번 클래스를 만든 뒤,inputFormattes에 추가해줌.
TextField(
inputFormatters: [
calorieInputFormatter,
CalorieUnitInputFormatter(Unit.kcal),
]
),