简体   繁体   中英

IndexOutOfBoundsException when setting text in EditText using TextWatcher addTextChangedListener()

I have a problem when change the text in EditText, my expected result is clear old text then set the new text that user input. After that, every working with editText is normal.

Exp: old text: 'abcdef',
     user press key 'k',
     expected text in editText is: 'k'

Here is my code:

editText.addTextChangedListener(new TextWatcher() {
private boolean firstRun = true;
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
    if(firstRun) {
        editText.removeTextChangedListener(this);
        firstRun = false;
        if(count == 0) {
        // Delete key or other special key
            editText.setText("");
            return;
        } else {
            if(s.length() > start) {
                editText.setText(String.valueOf(s.charAt(start)));
                editText.setSelection(etp.getEditText().getText().length());
            } else {
                editText.setText("");
            }
        }
   }

}

My code is crashed in case user paste a new text inside old text (it's not crashed if user paste from begin or end of old text).

Exp: Old text: abcdef
     User action: abcd(paste here)ef

The logcat is below

08-14 06:18:55.977: E/AndroidRuntime(4187): FATAL EXCEPTION: main
08-14 06:18:55.977: E/AndroidRuntime(4187): java.lang.IndexOutOfBoundsException: replace (-1 ... -1) starts before 0
08-14 06:18:55.977: E/AndroidRuntime(4187):     at android.text.SpannableStringBuilder.checkRange(SpannableStringBuilder.java:1021)
08-14 06:18:55.977: E/AndroidRuntime(4187):     at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:441)
08-14 06:18:55.977: E/AndroidRuntime(4187):     at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:435)
08-14 06:18:55.977: E/AndroidRuntime(4187):     at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:30)
08-14 06:18:55.977: E/AndroidRuntime(4187):     at android.widget.TextView.replaceText_internal(TextView.java:8442)
08-14 06:18:55.977: E/AndroidRuntime(4187):     at android.widget.TextView.prepareSpacesAroundPaste(TextView.java:8250)
08-14 06:18:55.977: E/AndroidRuntime(4187):     at android.widget.TextView.paste(TextView.java:8271)
08-14 06:18:55.977: E/AndroidRuntime(4187):     at android.widget.TextView.onTextContextMenuItem(TextView.java:8036)
08-14 06:18:55.977: E/AndroidRuntime(4187):     at android.widget.Editor$ActionPopupWindow.onClick(Editor.java:2862)
08-14 06:18:55.977: E/AndroidRuntime(4187):     at android.view.View.performClick(View.java:4204)
08-14 06:18:55.977: E/AndroidRuntime(4187):     at android.view.View$PerformClick.run(View.java:17355)
08-14 06:18:55.977: E/AndroidRuntime(4187):     at android.os.Handler.handleCallback(Handler.java:725)
08-14 06:18:55.977: E/AndroidRuntime(4187):     at android.os.Handler.dispatchMessage(Handler.java:92)
08-14 06:18:55.977: E/AndroidRuntime(4187):     at android.os.Looper.loop(Looper.java:137)
08-14 06:18:55.977: E/AndroidRuntime(4187):     at android.app.ActivityThread.main(ActivityThread.java:5041)
08-14 06:18:55.977: E/AndroidRuntime(4187):     at java.lang.reflect.Method.invokeNative(Native Method)
08-14 06:18:55.977: E/AndroidRuntime(4187):     at java.lang.reflect.Method.invoke(Method.java:511)
08-14 06:18:55.977: E/AndroidRuntime(4187):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
08-14 06:18:55.977: E/AndroidRuntime(4187):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
08-14 06:18:55.977: E/AndroidRuntime(4187):     at dalvik.system.NativeStart.main(Native Method)

What is causing this error?

This is an unintended side-effect of a feature that adds spaces before and after the text that was pasted. The big clue here is in the stack-trace:

08-14 06:18:55.977: E/AndroidRuntime(4187):     at android.widget.TextView.prepareSpacesAroundPaste(TextView.java:8250)

You've written code in the TextWatcher that sets the text to an empty string ( editText.setText("") ), but the code in prepareSpacesAroundPaste is expecting the original text. Hence the index out of range exception.

Solution: try doing your text replacement in the afterTextChanged event instead; you might need to have a flag set in onTextChanged that is referenced in afterTextChanged before updating your text value.

The addTextChangedListener() supports only a single character change at one time. So you are getting the error. So this listener won't help you for multiple text being pasted at once.

Solution So instead be tricky. Use hint .

yourTextView.setHint(oldPassword);

So pasting any key won't be a problem. Now you don't need addTextChangedListener() as well

PS

Use password inputType in XML as follow

android:inputType = password

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM