LineBackgroundSpan drawBackground()重复调用

时间:2017-04-25 13:07:55

标签: android android-layout android-edittext

修改:我已经能够将问题追踪到使用EditText而不是TextView。重复调用仅在字段为EditText时发生,并且当字段为TextView时系统自行运行。我在文档或在线中找不到任何内容,表明LineBackgroundSpan无法与EditText一起使用。

我更新了MCVE,以显示TextView(它确实如此)和EditText的工作原理(它没有 - 至少不是很好)。我的最新问题是LineBackgroundSpan如何使用EditText

我已经实现了一个简单的类,使用LineBackgroundSpanEditText中为文本添加圆角背景。一切正常但是在调试时我注意到我的类的drawBackground方法被重复调用,看起来,即使没有进行任何更改,字符串中的每个span都没有结束。它在显示屏上不明显,但如果在drawBackground方法中设置了断点,则很明显。

在尝试追踪问题时,我能够将代码缩减为MCVE。以下代码将简单地突出显示整行文本。顶行是EditText,底行是TextView。 (这不是我真正想要做的,但它有助于达到目的。)

此MCVE在运行API 17和API 24的模拟器以及运行API 24的实际手机上出现问题。将disableDraw参数设置为true,用于{{1}的构造函数}将禁用RoundedBackgroudSpan()中的背景绘制操作。即使禁用了背景图,我在drawBackground()上也看到了问题。

这里发生了什么?我是否误解了如何使用跨度?跨度不适用于EditText吗?任何帮助将不胜感激。

MainActivity.java

EditText

activity_main.xml中

    package com.example.bgspanmcve;

import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.SpannableString;
import android.text.style.LineBackgroundSpan;
import android.util.Log;
import android.widget.EditText;
import android.widget.TextView;

import static android.text.Spanned.SPAN_INCLUSIVE_INCLUSIVE;

public class MainActivity extends AppCompatActivity {
    final String dispString = "XAB CD EF";
    private static int count = 0; // times drawBackground is called

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        EditText editText;
        TextView textView;
        RoundedBackgroundSpan bg;

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Set up the EditText field with a span.
        // RoundedBackgroundSpan#drawBackground will be called forever for this EditText.
        editText = ((EditText) findViewById(R.id.editText));
        SpannableString ssEditText = new SpannableString(dispString);
        bg = new RoundedBackgroundSpan(INHIBIT_DRAWING, false);
        ssEditText.setSpan(bg, 0, ssEditText.length(), SPAN_INCLUSIVE_INCLUSIVE);
        editText.setText(ssEditText);

        // Set up the TextView field with a span.
        // RoundedBackgroundSpan#drawBackground will be called once for this TextView.
        textView = ((TextView) findViewById(R.id.textView));
        SpannableString ssTextView = new SpannableString(dispString);
        bg = new RoundedBackgroundSpan(INHIBIT_DRAWING, true);
        ssTextView.setSpan(bg, 0, ssTextView.length(), SPAN_INCLUSIVE_INCLUSIVE);
        textView.setText(ssTextView, TextView.BufferType.EDITABLE);
    }

    private static class RoundedBackgroundSpan implements LineBackgroundSpan {
        private boolean mDisableDraw;
        private boolean mIsTextView;

        RoundedBackgroundSpan(boolean disableDraw, boolean isTextView) {
            super();
            mDisableDraw = disableDraw;
            mIsTextView = isTextView;
        }

        @Override
        public void drawBackground(
                Canvas canvas, Paint paint, int left, int right, int top,
                int baseline, int bottom, CharSequence text, int start, int end, int lnum) {

            count++;
            if (mIsTextView) {
                Log.d(TAG, "<<<<drawBackground (TextView) #" + count);
            } else {
                Log.d(TAG, "<<<<drawBackground (EditText) #" + count);
            }
            if (mDisableDraw) return;

            Paint localPaint = new Paint();
            RectF rect = new RectF(left, top, right, bottom);
            localPaint.setColor(BG_COLOR);
            canvas.drawRoundRect(rect, RADIUS_X, RADIUS_Y, localPaint);
        }

        private final String TAG = RoundedBackgroundSpan.class.getSimpleName();
        private final int BG_COLOR = 0xfF00FF00;
        private final int RADIUS_X = 20;
        private final int RADIUS_Y = 20;
    }

    private final static String TAG = MainActivity.class.getSimpleName();
    private final boolean INHIBIT_DRAWING = true;
}

1 个答案:

答案 0 :(得分:1)

drawBackground()的调用是根据@Suragch建议的闪烁光标的速率计算的,大约500毫秒。我现在确信调用drawBackground()是作为游标实现的一部分。

作为一个快速但非确定性的测试,我将EditText字段设置为不显示光标但仍可编辑(android:cursorVisible="false")。当此属性设置为false时,对drawBackground()的重复调用将停止。