【问题标题】:IllegalArgumentException while selecting text in Android TextView在 Android TextView 中选择文本时出现 IllegalArgumentException
【发布时间】:2015-11-20 07:18:58
【问题描述】:

我在可选的 Android TextView 中取消选择文本时遇到了崩溃。当我选择 TextView 并设置 LinkMovementMethod 时会发生这种情况。

IllegalArgumentException in TextView

似乎这是 Android 内部的一个错误。

java.lang.IllegalArgumentException: Invalid offset: -1. Valid range is [0, 10562]
    at android.text.method.WordIterator.checkOffsetIsValid(WordIterator.java:380)
    at android.text.method.WordIterator.isBoundary(WordIterator.java:101)
    at android.widget.Editor$SelectionStartHandleView.positionAtCursorOffset(Editor.java:4260)
    at android.widget.Editor$HandleView.updatePosition(Editor.java:3708)
    at android.widget.Editor$PositionListener.onPreDraw(Editor.java:2507)
    at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:944)
    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2055)
    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1107)
    at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6013)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:858)
    at android.view.Choreographer.doCallbacks(Choreographer.java:670)
    at android.view.Choreographer.doFrame(Choreographer.java:606)
    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:844)
    at android.os.Handler.handleCallback(Handler.java:739)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:148)
    at android.app.ActivityThread.main(ActivityThread.java:5417)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

【问题讨论】:

    标签: android textview


    【解决方案1】:

    感谢 marriotaku 的回答。出于某种原因,我实际上不会在我的 TextView 中选择文本。我稍微调整了一下,只在选择某些字符时才触发工作。它现在似乎工作得很好!

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        // FIXME simple workaround to https://code.google.com/p/android/issues/detail?id=191430
        int startSelection = getSelectionStart();
        int endSelection = getSelectionEnd();
        if (startSelection != endSelection) {
            if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
                final CharSequence text = getText();
                setText(null);
                setText(text);
            }
        }
        return super.dispatchTouchEvent(event);
    }
    

    【讨论】:

    • 这只是救了我的命!非常感谢!
    • 我也遇到了类似的问题,这个方法需要保存在哪里。
    • 嘿@mVJ。您需要像下面的 marriotaku 的回答一样扩展 TextView。基本上看他的答案,但替换其中的 dispatchTouchEvent 方法。这将是您项目中名为 FixedTextView 的新文件(或任何您希望调用的文件),您将引用它而不是默认的 TextView
    • 你应该让 FixedTextView 扩展 AppCompatTextView,而不是 TextView
    • 为什么我们将 null 设置为 text(setText(null))
    【解决方案2】:

    我发现Android在调用setText时会清除TextView的选择,所以这里有一个简单的解决方法。

    public class FixedTextView extends TextView {
    
        public FixedTextView(final Context context) {
            super(context);
        }
    
        public FixedTextView(final Context context, final AttributeSet attrs) {
            super(context, attrs);
        }
    
        public FixedTextView(final Context context, final AttributeSet attrs, final int defStyle) {
            super(context, attrs, defStyle);
        }
    
        @Override
        public boolean dispatchTouchEvent(MotionEvent event) {
            // FIXME simple workaround to https://code.google.com/p/android/issues/detail?id=191430
            if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
                final CharSequence text = getText();
                setText(null);
                setText(text);
            }
            return super.dispatchTouchEvent(event);
        }
    
    }
    

    【讨论】:

    • 为什么我们将 null 设置为 text(setText(null))
    • @mariotaku 为什么我们在setText(text) 之前做setText(null)
    【解决方案3】:

    这是一个简单而完美的解决方法。你应该把它放到你的 Activity 类中:

    @Override
    public void onActionModeStarted(ActionMode mode) {
        super.onActionModeStarted(mode);
        yourTextView.setMovementMethod(ArrowKeyMovementMethod.getInstance());
    }
    
    @Override
    public void onActionModeFinished(ActionMode mode) {
        super.onActionModeFinished(mode);
        yourTextView.setMovementMethod(LinkMovementMethod.getInstance());
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-13
      • 1970-01-01
      • 2011-12-11
      • 1970-01-01
      • 2011-06-26
      • 1970-01-01
      • 2012-09-03
      • 2011-08-26
      相关资源
      最近更新 更多