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) {
/// nothing changes, nothing to do
if (newValue.text == _lastNewValue?.text) {
return newValue;
}
_lastNewValue = newValue;
/// remove all invalid characters
newValue = _formatValue(oldValue, newValue);
/// current selection
int selectionIndex = newValue.selection.end;
/// format original string, this step would add some separator
/// characters to original string
final newText = _formatPattern(newValue.text);
/// count number of inserted character in new string
int insertCount = 0;
/// count number of original input character in new string
int inputCount = 0;
for (int i = 0; i < newText.length && inputCount < selectionIndex; i++) {
final character = newText[i];
if (_isUserInput(character)) {
inputCount++;
} else {
insertCount++;
}
}
/// adjust selection according to number of inserted characters staying before
/// selection
selectionIndex += insertCount;
selectionIndex = min(selectionIndex, newText.length);
/// if selection is right after an inserted character, it should be moved
/// backward, this adjustment prevents an issue that user cannot delete
/// characters when cursor stands right after inserted characters
if (selectionIndex - 1 >= 0 &&
selectionIndex - 1 < newText.length &&
!_isUserInput(newText[selectionIndex - 1])) {
selectionIndex--;
}
return newValue.copyWith(
text: newText,
selection: TextSelection.collapsed(offset: selectionIndex),
composing: TextRange.empty);
}