formatEditUpdate method
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.
Implementation
@override
TextEditingValue formatEditUpdate(
TextEditingValue oldValue, TextEditingValue newValue) {
/// provides placeholder text when user start editing
if (oldValue.text.isEmpty) {
oldValue = oldValue.copyWith(
text: _placeholder,
);
newValue = newValue.copyWith(
text: _fillInputToPlaceholder(newValue.text),
);
return newValue;
}
/// nothing changes, nothing to do
if (newValue == _lastNewValue) {
return oldValue;
}
_lastNewValue = newValue;
int offset = newValue.selection.baseOffset;
/// restrict user's input within the length of date form
if (offset > 10) {
return oldValue;
}
if (oldValue.text == newValue.text && oldValue.text.length > 0) {
return newValue;
}
final String oldText = oldValue.text;
final String newText = newValue.text;
String? resultText;
/// handle user editing, there're two cases:
/// 1. user add new digit: replace '-' at cursor's position by user's input.
/// 2. user delete digit: replace digit at cursor's position by '-'
int index = _indexOfDifference(newText, oldText);
if (oldText.length < newText.length) {
/// add new digit
String newChar = newText[index];
if (index == 2 || index == 5) {
index++;
offset++;
}
resultText = oldText.replaceRange(index, index + 1, newChar);
if (offset == 2 || offset == 5) {
offset++;
}
} else if (oldText.length > newText.length) {
/// delete digit
if (oldText[index] != '/') {
resultText = oldText.replaceRange(index, index + 1, '-');
if (offset == 3 || offset == 6) {
offset--;
}
} else {
resultText = oldText;
}
}
/// verify the number and position of splash character
final splashes = resultText!.replaceAll(RegExp(r'[^/]'), '');
int count = splashes.length;
if (resultText.length > 10 ||
count != 2 ||
resultText[2].toString() != '/' ||
resultText[5].toString() != '/') {
return oldValue;
}
return oldValue.copyWith(
text: resultText,
selection: TextSelection.collapsed(offset: offset),
composing: defaultTargetPlatform == TargetPlatform.iOS
? TextRange(start: 0, end: 0)
: TextRange.empty,
);
}