0

I understand that IndexOutOfBounds exception is the most common error, but in my case it is showing up in some devices and working perfectly fine on others. What I was trying to do is get the last typed character in a Edittext and replace it with another character with the help of TextWatcher like this.

public TextWatcher textWatcher = new TextWatcher() {

    int selPos;

    boolean isNotBackspace = true;
    private String newTypedString = "";

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        selPos = editText.getSelectionStart();
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {

        isNotBackspace = count > before;
        newTypedString = s.subSequence(start, start + count).toString();
    }

    @Override
    public void afterTextChanged(Editable s) {
        editText.removeTextChangedListener(this);

        if (s.length() == 0) {
            isNotBackspace = true;
        } else if (isNotBackspace) {
            s.replace(editText.getSelectionEnd()-1, editText.getSelectionEnd(), changeTextChar(newTypedString));
        }

        editText.addTextChangedListener(this);

    }
};

For Clarification: The changeTextChar() is my custom method that provides a symbol when a character is passed. The backspace code is because I do not want to replace backspace with anything.

Problem: I am getting a runtime exception on afterTextChanged() which is caused by IndexOutOfBoundsException: replace (-1 ... 0) starts before 0 To my understanding, without writing anything TextWatcher will not invoke so in which case the index value is -1? Is there any alternative way to solve this? This error is appearing only in some devices, for other it just works fine.

3 Answers 3

1

You have to check the error condition in else if statement:

if (s.length() == 0) {
            isNotBackspace = true;
        } else if (isNotBackspace && editText.getSelectionEnd()>0) {
            s.replace(editText.getSelectionEnd()-1, editText.getSelectionEnd(), changeTextChar(newTypedString));
        }
Sign up to request clarification or add additional context in comments.

Comments

0

-1 means error value, that the index were not sucessfully found.

example:

"123".indexOf("0") == -1

everytime use 0 as a start index on strings, or check if index is -1 and replace it to 0 in case. but this should be an error in your code, i just want to describe you why your index is -1.

see indexof (for example) return values:

/**
 * Returns the index within this char sequence of the first occurrence of the specified [string],
 * starting from the specified [startIndex].
 *
 * @param ignoreCase `true` to ignore character case when matching a string. By default `false`.
 * @return An index of the first occurrence of [string] or `-1` if none is found.
 */
public fun CharSequence.indexOf(string: String, startIndex: Int = 0, ignoreCase: Boolean = false): Int {
    return if (ignoreCase || this !is String)
        indexOf(string, startIndex, length, ignoreCase)
    else
        nativeIndexOf(string, startIndex)
}

In Your case the watcher fail when nothing is selected probably, or there is no text, or index to end of selected text is 0. And You substract 1 and then You got -1, which does not exist in sequence of chars, starting on 0.

1 Comment

The whole TextWatcher starts when something is typed, right? and the else if (isNotBackspace) block is executed only when it's not backspace that is typed. So, what am I missing here?
0

first of all, from the code provided i dont understand what are you trying to do, but put whole code just to handler method called 'afterTextChanged' and remove properties from watcher, from outside of this method, and unsure if you need a backspace key code handling, but if so, the backspace key value is 8d or 0x08 (hex), but that you need to handle in onKey event, not in watcher, as watcher, i am not sure but it does not get the back key never, it will just remove last char from edit and decrease the whole string, next try to do something like this:

int startIdx = editText.getSelectionStart();
int endIdx = editText.getSelectionEnd();

if((startIdx>-1) && (endIdx>startIdx) && (startIdx<s.length()) && (endIdx<s.length())) {
    String selectedText = s.substring(startIdx, endIdx-startIdx);
    ...
} else {
    // not selected text or error
}

...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.