How to add a mask in a TextField in Flutter?
Solution 1
I modified some things and managed to get the expected result.
I created this class to define the variable
static final _UsNumberTextInputFormatter _birthDate = new _UsNumberTextInputFormatter();
class _UsNumberTextInputFormatter extends TextInputFormatter {
@override
TextEditingValue formatEditUpdate(
TextEditingValue oldValue,
TextEditingValue newValue ) {
final int newTextLength = newValue.text.length;
int selectionIndex = newValue.selection.end;
int usedSubstringIndex = 0;
final StringBuffer newText = new StringBuffer();
if (newTextLength >= 3) {
newText.write(newValue.text.substring(0, usedSubstringIndex = 2) + '/');
if (newValue.selection.end >= 2)
selectionIndex ++;
}
if (newTextLength >= 5) {
newText.write(newValue.text.substring(2, usedSubstringIndex = 4) + '/');
if (newValue.selection.end >= 4)
selectionIndex++;
}
if (newTextLength >= 9) {
newText.write(newValue.text.substring(4, usedSubstringIndex = 8));
if (newValue.selection.end >= 8)
selectionIndex++;
}
// Dump the rest.
if (newTextLength >= usedSubstringIndex)
newText.write(newValue.text.substring(usedSubstringIndex));
return new TextEditingValue(
text: newText.toString(),
selection: new TextSelection.collapsed(offset: selectionIndex),
);
}
}
And finally I added an inputformat to the textfield
new TextFormField(
maxLength: 10,
keyboardType: TextInputType.datetime,
validator: _validateDate,
decoration: const InputDecoration(
hintText: 'Digite sua data de nascimento',
labelText: 'Data de Nascimento',
),
inputFormatters: <TextInputFormatter> [
WhitelistingTextInputFormatter.digitsOnly,
// Fit the validating format.
_birthDate,
]
),
Now it's all right, thank you
Solution 2
https://pub.dartlang.org/packages/masked_text
masked_text
A package for masked texts, so if you want a mask for phone, or zip code or any kind of mask, just use it :D
Getting Started
It's very simple, it's a Widget as all the other ones.
new MaskedTextField
(
maskedTextFieldController: _textCPFController,
mask: "xx/xx/xxxx",
maxLength: 10,
keyboardType: TextInputType.number,
inputDecoration: new InputDecoration(
hintText: "Digite a data do seu nascimento", labelText: "Data"),
);
'x' is the normal char that your text will have.
this sample reproduces something like this in the end: 11/02/1995
.
Solution 3
My solution:
class MaskTextInputFormatter extends TextInputFormatter {
final int maskLength;
final Map<String, List<int>> separatorBoundries;
MaskTextInputFormatter({
String mask = "xx.xx.xx-xxx.xx",
List<String> separators = const [".", "-"],
}) : this.separatorBoundries = {
for (var v in separators)
v: mask.split("").asMap().entries.where((entry) => entry.value == v).map((e) => e.key).toList()
},
this.maskLength = mask.length;
@override
TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) {
final int newTextLength = newValue.text.length;
final int oldTextLength = oldValue.text.length;
// removed char
if (newTextLength < oldTextLength) return newValue;
// maximum amount of chars
if (oldTextLength == maskLength) return oldValue;
// masking
final StringBuffer newText = StringBuffer();
int selectionIndex = newValue.selection.end;
// extra boundaries check
final separatorEntry1 = separatorBoundries.entries.firstWhereOrNull((entry) => entry.value.contains(oldTextLength));
if (separatorEntry1 != null) {
newText.write(oldValue.text + separatorEntry1.key);
selectionIndex++;
} else {
newText.write(oldValue.text);
}
// write the char
newText.write(newValue.text[newValue.text.length - 1]);
return TextEditingValue(
text: newText.toString(),
selection: TextSelection.collapsed(offset: selectionIndex),
);
}
}
Victor Henrique
Updated on July 09, 2022Comments
-
Victor Henrique almost 2 years
I'm trying to add a date mask to a textField since I did not like the Date Picker because for date of birth, for example, it is not as nimble. After that, converting from string to datetime, I believe I can continue the project, Thanks in advance.
static final TextEditingController _birthDate = new TextEditingController(); new TextFormField( controller: _birthDate, maxLength: 10, keyboardType: TextInputType.datetime, validator: _validateDate ), String _validateDate(String value) { if(value.isEmpty) return null; if(value.length != 10) return 'Enter date in DD / MM / YYYY format'; return null; }
-
Hardy over 4 yearsit is just going into infinite loop that library is unfortunately not working.
-
Renan Coelho over 4 yearsdon't use this. here is a better approach using the native TextField widget: pub.dev/packages/mask_text_input_formatter
-
TootsieRockNRoll over 4 years@RenanCoelho do you update the text manually later on and keep the format?