Android: Handle backspace on InputFilter

2.4k views Asked by At

I created an InputFilter for an EditText component that only allows doubles within a range (e.g. from 1.5 to 5.5). Everything worked fine until I deleted the decimal point:

I typed 1.68 and then deleted the decimal point. The value in the text field became 168, which is obviously outside the range.

Here is a simplified version of my filter

public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
        if (isValid(dest.toString() + source.toString())) {
            //input is valid
            return null;
        }else{
          //The input is not valid
            return "";
        }
}
private boolean isValid(String input) {
    Double inputValue = Double.parseDouble(input);
    boolean isMinValid = (1.5 <= inputValue);
    boolean isMaxValid = (5.5 >= inputValue);

    return  isMinValid && isMaxValid;
}
3

There are 3 answers

1
user2287966 On BEST ANSWER

I solved my problem. Here is the solution in case someone else needs it:

public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
    if (isValid(dest.toString() + source.toString())) {
        //input is valid
        return null;
    }else{
      //The input is not valid
       if (source.equals("") && dest.toString().length() != 1) {
            //backspace was clicked, do not accept that change, 
            //unless user is deleting the last char
            CharSequence deletedCharacter = dest.subSequence(dstart, dend);
            return deletedCharacter;
        }
        return "";
    }

}

1
Miki Franko On

When you are finished entering data in the edit text, you have to trigger knowing you have finished entering data and now have to check the input. For example by adding input test button, or for example when the edit text field loses focus.

0
Nicolas400 On

In my case, I need a range validation, let's say between 0 and 500.

5 is ok
55 is ok
555 is Error

But for clarity to the user, if the digit entered by the user ends in a number outside the range, I want to show the final number and a message to the user ( i'm using Material TextInputLayout), but the backspace button wasn't working as expected.

Your solution give me an idea:

...
        try {
            val input = if (source.toString() != "") {
                Integer.parseInt(dest.toString() + source.toString())
            }
            else {
                Integer.parseInt(dest?.replaceRange(dstart, dend, source.toString()).toString())
            }
            if (isInRange(intMin, intMax, input)) {
                //Input Valido
                return null
            } else {
                //Input Invalido
                if (source.toString() == "" && dest.toString().length != 1) {
                    //return dest?.subSequence(dstart, dend)
                    return null
                }
                textInputLayout?.error = "Rango no vĂ¡lido!"
                return null //Deja el caracter, si devuelve "" no imprime el caracter
            }
        } catch (e: NumberFormatException) {
            e.printStackTrace()
        }

If the user press backspace,

source is ""
dest is the actual number, 555
and "dstart" and "dend" are the index to replace.(2 and 3)

It work for me, at least Best Regards