简体   繁体   English

使用TextWatcher addTextChangedListener()在EditText中设置文本时的IndexOutOfBoundsException

[英]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. 我在EditText中更改文本时遇到问题,我的预期结果是清除旧文本然后设置用户输入的新文本。 After that, every working with editText is normal. 之后,每个使用editText都是正常的。

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 logcat在下面

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. 您已在TextWatcher了将文本设置为空字符串( editText.setText("") )的代码,但prepareSpacesAroundPaste的代码需要原始文本。 Hence the index out of range exception. 因此索引超出范围异常。

Solution: try doing your text replacement in the afterTextChanged event instead; 解决方案:尝试在afterTextChanged事件中替换文本; you might need to have a flag set in onTextChanged that is referenced in afterTextChanged before updating your text value. 在更新文本值之前,您可能需要在onTextChanged中引用afterTextChanged设置一个标志。

The addTextChangedListener() supports only a single character change at one time. addTextChangedListener()只支持一个字符更改。 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 现在你也不需要addTextChangedListener()

PS PS

Use password inputType in XML as follow 在XML中使用密码inputType如下

android:inputType = password

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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