1

I entered 3 alphabet character android clears input. I expected to remove last , 3rd character, not full text

enter image description here

update , removed regex regarding comment below and still same result

private final Integer mAlphabetCount = 2;

@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {

    String text = createResultString(source, start, end, dest, dstart, dend);

    if (text.length() <= mAlphabetCount) {
        for (int i = start; i < end; i++) {
            if (!Character.isLetter((source.charAt(i)))) {
                return "";
            }
        }
        return null;
    }

    char[] digit = text.substring(2).toCharArray();
    for (char c : digit) {
        if (!Character.isDigit(c)) {
            return "";
        }
    }

    return source;
}

private String createResultString(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
    String sourceString = source.toString();
    String destString = dest.toString();
    return destString.substring(0, dstart) + sourceString.substring(start, end) + destString.substring(dend);
}
Nininea
  • 2,671
  • 6
  • 31
  • 57

2 Answers2

0

UPDATED

First of all you need to decide what you want to happen in case of wrong user input. For example, the user already entered "AB" and now tries to enter "C". Do you want to discard the "C"? Do you want the input field to become "BC"? Let's say you want to discard the "C".

Check if source is an instance of Spanned. If so, then you cannot just send back an empty String if the input is invalid, or it will erase the textbox (this is happening to you now). You need to extract the correct part from the source and send it back. Since we decided to just discard all letters after the first 2 you can try to match source against ^([a-zA-Z]{0,2})(?:[^\d]*)(\d{0,7}). Then send back the result composed of matching group 1 + group 2, i.e. first 2 letters + first 7 digits.

If source is not an instance of Spanned you can check if dest + source matches ^[a-zA-Z]{0,2}\d{0,7}$. If yes, send back null, otherwise discard the input - send back an empty string.

Alex Sveshnikov
  • 4,214
  • 1
  • 10
  • 26
  • thanks for answer, but the problem is that after first check [A-Za-z]{0,2} < it works good, if the 3rd character is incorrect android clears whole textview :( – Nininea Feb 25 '20 at 13:15
  • Aha, so you have a problem with a dictionary completion. Check the answer to this question: https://stackoverflow.com/questions/3349121/how-do-i-use-inputfilter-to-limit-characters-in-an-edittext-in-android – Alex Sveshnikov Feb 25 '20 at 13:32
  • can you add tested example as answer ? For example, the user already entered "AB" and now tries to enter "C". Do you want to discard the "C"? - yes "C" should be dismissed. I tested several variants and doesn't work correctly . – Nininea Feb 25 '20 at 16:55
0

Here is all I need, actually there are no need to use regex, but it will work the same way. answer reference

public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
    if (source instanceof SpannableStringBuilder) {
        SpannableStringBuilder sourceAsSpannableBuilder = (SpannableStringBuilder) source;
        for (int i = end - 1; i >= start; i--) {
            char currentChar = source.charAt(i);
            if (i < mAlphabetCount) {
                if (!Character.isLetter(currentChar)) {
                    sourceAsSpannableBuilder.delete(i, i + 1);
                }
            } else {
                if (!Character.isDigit(currentChar)) {
                    sourceAsSpannableBuilder.delete(i, i + 1);
                }
            }
        }
        return source;
    } else {
        StringBuilder filteredStringBuilder = new StringBuilder();
        for (int i = start; i < end; i++) {
            char currentChar = source.charAt(i);
            if (dest.length() < mAlphabetCount) {
                if (Character.isLetter(currentChar)) {
                    filteredStringBuilder.append(currentChar);
                }
            } else {
                if (Character.isDigit(currentChar)) {
                    filteredStringBuilder.append(currentChar);
                }
            }
        }
        return filteredStringBuilder.toString();
    }
}
Nininea
  • 2,671
  • 6
  • 31
  • 57