formatEditUpdate method

  1. @override
TextEditingValue formatEditUpdate(
  1. TextEditingValue oldValue,
  2. TextEditingValue newValue
)
override

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);
}