【问题标题】:EditText.setText() gives index out of boundsEditText.setText() 给出的索引超出范围
【发布时间】:2012-07-03 21:16:02
【问题描述】:

我遇到了一个我似乎无法理解的错误。我正在编写一个应用程序,允许用户将文本从EditText 发送到TextView。如果用户出错,用户可以按空格键将EditText 发送的最新文本带到TextView。这有时有效,但其他时候,它给了我一个IndexOutOfBounds 异常。

textInput是一个EditText,back1,2,3是最近的三个字符串(back1是最近的)

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

    if(count==1&&before==0&&s.toString().equals(" ")){
        textInput.setText(back1);
    }else if(s.toString().equals(back1 + " ")){
        textInput.setText(back2);
    }else if(s.toString().equals(back2 + " ")){
        textInput.setText(back3); //causes error if back2 > back3
    }

    textInput.setSelection(textInput.getText().toString().length());

上面的代码检查用户是否按下了空格键,如果是,如何处理。如果用户在空的 EditText 上按下空格,他们会得到他们发送的最后一件事。如果他们再次命中空间,他们会得到他们发送的最后一个东西,依此类推。这仍然有点粗糙,但我希望你能明白。

OutOfBounds 异常来自于在EditText 中获取一个大项目,点击空格,并将EditText 设置为一个较小的字符串。我认为这是因为光标位于EditText 的末尾并且当文本变小时不再存在,所以我尝试在setText() 之前添加textInput.setSelection(0)。那没有帮助。我还尝试将EditText 设置为setText("")。那也没有用。如果我注释掉setText(back#) 的行,一切正常。

一个例子:

用户按“hello”、“hi”和“hey”的顺序输入。

back3 = hello,back2 = hi,back1 = hey。

点击空格一次会将 EditText 设置为“嘿”

第二次点击会崩溃,因为setSpan(3...4) ends beyond length 2,大概是因为后退1大于后退2。它应该将EditText中的文本设置为“hi”

【问题讨论】:

  • 我没有阅读整个问题,但应该行 textInput.setSelection(textInput.getText().toString().length());不是 textInput.setSelection(textInput.getText().toString().length() - 1);?
  • 不,setSelection() 在从 small->large 开始时按预期工作。此外,错误不止一个。

标签: android android-edittext indexoutofboundsexception


【解决方案1】:

来自the TextWatcher documentation

public abstract void onTextChanged (CharSequence s, int start, int before, int count)

自:API 级别 1

调用此方法是为了通知您,在s 中,以start 开头的count 字符刚刚替换了长度为before 的旧文本。 尝试通过此回调对s 进行更改是错误的。

(我的重点。)

如果您想更多地更改文本以响应现有更改,则应改用afterTextChanged。即使在这种情况下,当您从 afterTextChanged 更改文本时,您的处理程序也会被重新调用,因此请采取额外的预防措施以确保您不会陷入无限循环,例如:

public void afterTextChanged (Editable s) {
    static boolean is_reentrant = false;

    if (!is_reentrant) {
        is_reentrant = true;
        
        try {
            // do stuff
        } finally {
            is_reentrant = false;
        }
    }
}

我还没有测试过这个确切的 sn-p,但是类似的东西会让你的代码只有在它还没有运行时才运行。在这种情况下,您无需担心线程安全,因为它只会从同一个线程内部调用。

【讨论】:

  • 啊,我误解了 s 是什么。我在想这是 EditText 中文本的新字符串副本。我不认为它是 EditText 中文本的实际对象。它是编辑文本中的实际文本对象吗?无论哪种方式,将其移至 afterTextChanged 似乎都有效。谢谢。
  • 我不知道是实际对象,还是onTextChanged返回后进一步处理的副本,但是s的更改反映在@的内容中987654333@.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-03-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-28
  • 2012-05-04
相关资源
最近更新 更多