Android TextView 给出 IndexOutOfBoundsException TextLine.handleRun

tam*_*tom 5 android

我不久前就遇到了这个异常,我无法从堆栈跟踪中找到任何有用的信息,Crashlytics 报告它发生在 Android 8 和 9 上

这是堆栈跟踪:

Fatal Exception: java.lang.IndexOutOfBoundsException: measureLimit (54) is out of start (55) and limit (54) bounds
       at android.text.TextLine.handleRun(TextLine.java:989)
       at android.text.TextLine.measureRun(TextLine.java:500)
       at android.text.TextLine.measure(TextLine.java:337)
       at android.text.TextLine.metrics(TextLine.java:272)
       at android.text.Layout.getLineExtent(Layout.java:1370)
       at android.text.Layout.drawText(Layout.java:519)
       at android.text.Layout.draw(Layout.java:292)
       at android.widget.TextView.onDraw(TextView.java:7765)
       at android.view.View.draw(View.java:20370)
       at android.view.View.updateDisplayListIfDirty(View.java:19315)
       at android.view.View.draw(View.java:20093)
       at android.view.ViewGroup.drawChild(ViewGroup.java:4421)
       at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4207)
       at android.view.View.updateDisplayListIfDirty(View.java:19306)
       at android.view.View.draw(View.java:20093)
       at android.view.ViewGroup.drawChild(ViewGroup.java:4421)
       at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4207)
       at android.view.View.draw(View.java:20373)
       at android.support.v4.widget.NestedScrollView.draw(NestedScrollView.java:1888)
       at android.view.View.updateDisplayListIfDirty(View.java:19315)
       at android.view.View.draw(View.java:20093)
       at android.view.ViewGroup.drawChild(ViewGroup.java:4421)
       at android.support.design.widget.CoordinatorLayout.drawChild(CoordinatorLayout.java:1246)
       at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4207)
       at android.view.View.updateDisplayListIfDirty(View.java:19306)
       at android.view.View.draw(View.java:20093)
       at android.view.ViewGroup.drawChild(ViewGroup.java:4421)
       at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4207)
       at android.view.View.updateDisplayListIfDirty(View.java:19306)
       at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4405)
       at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4385)
       at android.view.View.updateDisplayListIfDirty(View.java:19274)
       at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4405)
       at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4385)
       at android.view.View.updateDisplayListIfDirty(View.java:19274)
       at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4405)
       at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4385)
       at android.view.View.updateDisplayListIfDirty(View.java:19274)
       at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4405)
       at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4385)
       at android.view.View.updateDisplayListIfDirty(View.java:19274)
       at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4405)
       at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4385)
       at android.view.View.updateDisplayListIfDirty(View.java:19274)
       at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4405)
       at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4385)
       at android.view.View.updateDisplayListIfDirty(View.java:19274)
       at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4405)
       at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4385)
       at android.view.View.updateDisplayListIfDirty(View.java:19274)
       at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:686)
       at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:692)
       at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:800)
       at android.view.ViewRootImpl.draw(ViewRootImpl.java:3494)
       at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:3281)
       at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2816)
       at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1785)
       at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7825)
       at android.view.Choreographer$CallbackRecord.run(Choreographer.java:911)
       at android.view.Choreographer.doCallbacks(Choreographer.java:723)
       at android.view.Choreographer.doFrame(Choreographer.java:658)
       at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:897)
       at android.os.Handler.handleCallback(Handler.java:789)
       at android.os.Handler.dispatchMessage(Handler.java:98)
       at android.os.Looper.loop(Looper.java:164)
       at android.app.ActivityThread.main(ActivityThread.java:6944)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)
Run Code Online (Sandbox Code Playgroud)

所以堆栈跟踪没有向我提供正在TextView发生的情况,我正在记录发生崩溃的屏幕,并且该屏幕有很多TextView,我搜索了整个网络,但找不到答案。

更新

我怀疑这段代码是否为电话号码绘制了圆形背景TextView

public class RoundedBackgroundSpan extends ReplacementSpan implements LineHeightSpan {

    private static int CORNER_RADIUS = 8;
    private int backgroundColor = 0;
    private int textColor = 0;
    private int backgroundTranspernt;
    private float mTextSize = UIUtils.spToPx(16);

    private static final float PADDING_X = UIUtils.dp2px(4);
    private static final float PADDING_Y = UIUtils.dp2px(2);
    private static final float MAGIC_NUMBER = UIUtils.dp2px(2);

    public RoundedBackgroundSpan(Context context) {
        super();
        backgroundColor = context.getResources().getColor(R.color.NavigationBarStrokeColor);
        textColor = context.getResources().getColor(R.color.white);
        backgroundTranspernt = context.getResources().getColor(R.color.transparent);
    }

    public RoundedBackgroundSpan(Context context, @ColorRes int textColor,
                                 @ColorRes int backgroundColor) {
        super();
        this.backgroundColor = context.getResources().getColor(backgroundColor);
        this.textColor = context.getResources().getColor(textColor);
        backgroundTranspernt = context.getResources().getColor(backgroundColor);
    }

    @Override
    public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int
            y, int bottom, Paint paint) {


        paint = new Paint(paint); // make a copy for not editing the referenced paint

        paint.setTextSize(mTextSize);

        // Draw the rounded background
        paint.setColor(backgroundColor);
        float textHeightWrapping = UIUtils.dp2px(0);
        float tagBottom =
                top + textHeightWrapping + PADDING_Y + mTextSize + PADDING_Y + textHeightWrapping;
        float tagRight = x + getTagWidth(text, start, end, paint);
        RectF rect = new RectF(x, top, tagRight, tagBottom);
        canvas.drawRoundRect(rect, CORNER_RADIUS, CORNER_RADIUS, paint);

        // Draw the text
        paint.setColor(textColor);
        canvas.drawText(text, start, end, x + PADDING_X,
                tagBottom - PADDING_Y - textHeightWrapping - MAGIC_NUMBER, paint);

    }

    @Override
    public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt
            fm) {
        paint = new Paint(paint); // make a copy for not editing the referenced paint
        paint.setTextSize(mTextSize);
        return getTagWidth(text, start, end, paint);
    }

    private int getTagWidth(CharSequence text, int start, int end, Paint paint) {
        return Math.round(PADDING_X + paint.measureText(text.subSequence(start, end).toString()) + PADDING_X);
    }

    @Override
    public void chooseHeight(CharSequence text, int start, int end, int i2, int i3,
                             Paint.FontMetricsInt fontMetricsInt) {
        //we need to implement this so the text know the  line height
    }
}
Run Code Online (Sandbox Code Playgroud)

它掩盖了手机,使其可以通过 clickSpan 点击

在此输入图像描述

Cly*_*yde 1

此错误与添加到TextView. 您引用的圆形背景不相关,因为错误具体与文本相关,而不是TextView.

TextView如果从主线程以外的线程进行操作,则可能会发生该错误。确保任何涉及 UI 小部件的代码仅在主线程上执行。如果您正在使用 RxJava,请确保您在必要时正确使用了它observeOn(AndroidSchedulers.mainThread()