flutter_multi_formatter icon indicating copy to clipboard operation
flutter_multi_formatter copied to clipboard

CurrencyInputFormatter - Incorrect cursor position when typing 0 with a leading symbol

Open nizioleque opened this issue 1 year ago • 1 comments

I am using the CurrencyInputFormatter with a leading symbol (let's say EUR).

When I enter a non-zero digit the cursor is positioned correctly next to the period (which is correct an expected behavior) - example: in an empty field I input 1. The result is EUR1|.00 where | is the cursor position.

But when I enter 0, the cursor is not positioned correctly - example: in an empty field I input 0. The result is E|UR0.00.

I would appreciate a fix for this issue :)

nizioleque avatar Jul 08 '23 15:07 nizioleque

Here is my temporary walkaround for this issue:

I add two formatters before and after the CurrencyInputFormatter - the first one detects this issue, changes the 0 to a 1, then CurrencyInputFormatter sets the cursor position correctly, then the second one changes the 1 back to a 0. A List is used to pass the boolean by reference.

In the widget:

List<bool> shouldReplace = [false];

// ...

TextFormField(
  inputFormatters: [
    FixZeroBeforeInputFormatter(shouldReplace),
    CurrencyInputFormatter(leadingSymbol: 'EUR'),
    FixZeroAfterInputFormatter(shouldReplace)
  ],
)

and here are the formatters:

class FixZeroBeforeInputFormatter extends TextInputFormatter {
  FixZeroBeforeInputFormatter(this.shouldReplace);

  List<bool> shouldReplace;

  @override
  TextEditingValue formatEditUpdate(
    TextEditingValue oldValue,
    TextEditingValue newValue,
  ) {
    if (newValue.text == '0') {
      shouldReplace[0] = true;
      return newValue.copyWith(text: '1');
    }

    return newValue;
  }
}

class FixZeroAfterInputFormatter extends TextInputFormatter {
  FixZeroAfterInputFormatter(this.shouldReplace);

  List<bool> shouldReplace;

  @override
  TextEditingValue formatEditUpdate(
    TextEditingValue oldValue,
    TextEditingValue newValue,
  ) {
    bool tmpShouldReplace = shouldReplace[0];
    shouldReplace[0] = false;

    if (tmpShouldReplace) {
      String newText = newValue.text.replaceFirst('1', '0');
      return newValue.copyWith(text: newText);
    }

    return newValue;
  }
}

nizioleque avatar Jul 08 '23 15:07 nizioleque