EditText在清除文本时崩溃

时间:2018-12-12 18:18:28

标签: android android-edittext

我想从EditText清除文本。 我尝试过:

  • editText.setText("")
  • editText.text.clear()
  • editText.editableText.clear()

它可以工作。但是有时会有例外。

2018-12-11 16:23:44.367 13388-13388/com.example.helios.myapplication E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.helios.myapplication, PID: 13388
    java.lang.IndexOutOfBoundsException: setSpan (0 ... 6) ends beyond length 0
        at android.text.SpannableStringBuilder.checkRange(SpannableStringBuilder.java:1265)
        at android.text.SpannableStringBuilder.setSpan(SpannableStringBuilder.java:684)
        at android.text.SpannableStringBuilder.setSpan(SpannableStringBuilder.java:677)
        at android.widget.Editor$SuggestionsPopupWindow.updateSuggestions(Editor.java:3608)
        at android.widget.Editor$SuggestionsPopupWindow.show(Editor.java:3480)
        at android.widget.Editor.replace(Editor.java:359)
        at android.widget.Editor$3.run(Editor.java:2129)
        at android.os.Handler.handleCallback(Handler.java:751)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6119)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776

我从覆盖的performClick()(正在创建EditText的子类)中执行该代码。

EditText似乎没有意识到它应该取消/忘记建议机制,但失败了。

您知道我应该采取什么特殊措施来取消/阻止失败的建议吗?

我注意到,如果我使弹出窗口出现,然后在X上单击两次,则会发生异常(第一个关闭弹出窗口,第二个执行清除代码)。

更新

代码的相关部分。实际的代码有一个插件系统来添加不同的图形和动作,但是相关的代码是这样的:

    class MyEditText(..): EditText(context) {
    ... 
        override fun onTouchEvent(event: MotionEvent?): Boolean {
            event!!
            ensureDrawingInfo()
            when (event.actionMasked) {
                MotionEvent.ACTION_DOWN, MotionEvent.ACTION_CANCEL, MotionEvent.ACTION_UP -> {
                    lastTouchArea = pluginAreaFromMotionEvent(event)
                }
            }
            return super.onTouchEvent(event)
        }

        override fun performClick(): Boolean {
            lastTouchArea?.let {
                plugins[it.pluginIndex].onClick(this, it.rightSide, ::invalidateDrawingInfo)
                return true
            }
            return super.performClick()
        }


    class MyPlugin(val drawableLeft: Drawable, val drawableRight: Drawable) : Plugin {
        ....

        override fun onClick(editText: MyEditText, rightSide: Boolean, redraw: () -> Unit) {
            if (rightSide) {
                // X
                editText.text.clearSpans()
                editText.text.clear()
            }
        }
    }

2 个答案:

答案 0 :(得分:1)

问题是您在setSpan中更改文本后尝试“ EditText”进行“ updateSuggestions”。 因此,您需要在编辑器修改EditText之后更改文本。只需将您的代码放入view.post

科特琳

mEditText.post {
   mEditText.setText("your text")
}

Java

mEditText.post(new Runnable() {
        @Override
        void run() {
            mEditText.setText("your text");
        }
    });

答案 1 :(得分:0)

我找到了一种避免该问题的方法:消耗我感兴趣的触摸事件。

我想对编辑框某个角落的点击做出反应(想想一个明文按钮或一个查看密码)。

我首先尝试仅使用onTouchEvent,因为我需要坐标。但是IDE提醒我不要出于可访问性原因也不要覆盖performClick。这个想法是,如果您在触摸时添加了其他行为,则调用performClick的辅助功能工具也应该可以使用它。

但事实并非如此。额外的按钮是不需要使用的额外功能。或者,如果可用,则不能通过正常/常规单击编辑框来使用。也许是在其他地方实施的可访问性操作。

因此,结论:我只能使用onTouchEvent并使用事件。

解决方案

override fun onTouchEvent(event: MotionEvent?): Boolean {
        event!!
        ensureDrawingInfo()
        val touchArea = pluginAreaFromMotionEvent(event)
        if (touchArea != null) {
          // it's the special place, I will handle this
          when (event.actionMasked) {
              MotionEvent.ACTION_DOWN -> lastTouchArea = touchArea
              MotionEvent.ACTION_CANCEL -> lastTouchArea = null
              MotionEvent.ACTION_UP -> {
                if (lastTouchArea == touchArea) { // proper click on place
                  // call the plugin
                  plugins[touchArea.pluginIndex].onClick(this, it.rightSide, ::invalidateDrawingInfo)
              }
          }
          // consume touch events that happen on MY area
          return true
        }
        return super.onTouchEvent(event)
    }

为什么

EditText编辑器有时会打开一个建议窗口以响应触摸事件。并且它想在特定位置替换文本。但是它并不能立即取代它。它使消息排队,以便以后使用循环程序进行处理),因此在进行替换时,我可能已更改了文本。我甚至试图将清算代码放入队列中,以希望稍后发生,但是我很不幸。

最干净的解决方案是消耗与我正在处理的区域相关的事件,以使编辑器不会引发任何问题。

实际上,在API 27仿真器上运行它无法重现该错误。我想编辑器代码已更改为意识到文本可能在两者之间进行了更改。