Android 重复调用LineBackgroundSpan drackground()

Android 重复调用LineBackgroundSpan drackground(),android,android-layout,android-edittext,Android,Android Layout,Android Edittext,编辑:我已经能够追踪到问题的根源是EditText的使用,而不是TextView。重复调用仅在字段为EditText时发生,并且当字段为TextView时系统会自行运行。我在文档或网上找不到任何东西表明LineBackgroundSpan不能与EditText一起使用 我已经更新了MCVE,以显示如何使用TextView(它可以)和EditText(它不能-至少不能很好地工作)。我最新的问题是如何获得LineBackgroundSpan使用EditText 我已经实现了一个简单的类,用它向Ed

编辑:我已经能够追踪到问题的根源是
EditText
的使用,而不是
TextView
。重复调用仅在字段为
EditText
时发生,并且当字段为
TextView
时系统会自行运行。我在文档或网上找不到任何东西表明
LineBackgroundSpan
不能与
EditText
一起使用

我已经更新了MCVE,以显示如何使用
TextView
(它可以)和
EditText
(它不能-至少不能很好地工作)。我最新的问题是如何获得
LineBackgroundSpan
使用
EditText


我已经实现了一个简单的类,用它向
EditText
中的文本添加圆形背景。一切正常,但在调试过程中,我注意到类的
traffackground
方法被反复调用,而且似乎字符串中的每个跨度都没有结束,即使没有进行任何更改。它在显示屏上不明显,但如果在
牵引地面
方法中设置了断点,则很明显

在试图追踪问题的过程中,我将代码简化为MCVE。顶行是一个
编辑文本
,底行是一个
文本视图
。(这不是我真正想做的,但它达到了目的。)

这个MCVE向我展示了运行API 17和API 24的模拟器以及运行API 24的实际手机的问题。将
roundedbackgroundspan()
的构造函数的
disableDraw
参数设置为
true
,将禁用
drackground()中的背景绘图操作。即使在禁用背景绘图的情况下,
EditText
上也出现了问题

这是怎么回事?我是否误解了如何使用跨度?span不能使用
EditText
?任何帮助都将不胜感激

MainActivity.java

    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;
}
package com.example.bgspanmcve;
导入android.graphics.Canvas;
导入android.graphics.Paint;
导入android.graphics.RectF;
导入android.os.Bundle;
导入android.support.v7.app.AppActivity;
导入android.text.SpannableString;
导入android.text.style.LineBackgroundSpan;
导入android.util.Log;
导入android.widget.EditText;
导入android.widget.TextView;
导入静态android.text.SPAN.SPAN_INCLUSIVE_INCLUSIVE;
公共类MainActivity扩展了AppCompatActivity{
最终字符串dispString=“XAB CD EF”;
private static int count=0;//调用trackground的次数
@凌驾
创建时受保护的void(Bundle savedInstanceState){
编辑文本编辑文本;
文本视图文本视图;
圆形背景跨度bg;
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//设置带有跨距的EditText字段。
//RoundedBackgroundSpan#此编辑文本将永远调用trackground。
editText=((editText)findViewById(R.id.editText));
SpannableString ssEditText=新的SpannableString(dispString);
bg=新的圆形背景跨度(禁止绘制,错误);
ssEditText.setSpan(bg,0,ssEditText.length(),包含SPAN_);
editText.setText(ssEditText);
//设置带有跨距的TextView字段。
//RoundedBackgroundSpan#将为此TextView调用一次牵引地面。
textView=((textView)findViewById(R.id.textView));
SpannableString ssTextView=新的SpannableString(dispString);
bg=新的圆形背景跨度(抑制图,真);
ssTextView.setSpan(bg,0,ssTextView.length(),包含SPAN_);
textView.setText(ssTextView,textView.BufferType.EDITABLE);
}
私有静态类RoundedBackgroundSpan实现LineBackgroundSpan{
私有布尔mDisableDraw;
私有布尔文本视图;
RoundedBackgroundSpan(布尔禁用绘制,布尔isTextView){
超级();
mDisableDraw=禁用绘制;
mIsTextView=isTextView;
}
@凌驾
公共空地(
帆布,油漆,左整数,右整数,顶部整数,
int基线、int底部、字符序列文本、int开始、int结束、int lnum){
计数++;
if(mIsTextView){

Log.d(TAG,“对
牵引地面()
的调用按照@Suragch建议的大约500毫秒的闪烁光标的速率进行计时。我现在确信,对
牵引地面()
的调用是作为光标实现的一部分进行的


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

你找到你的答案了吗?多久调用一次
EditText
?这可能与光标闪烁率有关吗?@Suragh我没有找到这个问题的答案。我只是回去检查有多少次调用
退税地
。当前计数是1426,并且增加了大约2倍/秒。我可以避免如果我在应用span之前清除了所有span,则会出现问题,因此似乎存在导致此问题的潜在span交互。这是一个无声的问题,在屏幕或性能上不明显。我碰巧发现了它,因为我在
trackground
中设置了断点。至于光标闪烁率,光标隐藏在后面背景和我对速率没有任何影响。@Sugarch我认为你对光标闪烁速率的看法是正确的。通话是以光标闪烁的速率计时的。我认为
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.bgspanmcve.MainActivity">

    <EditText
        android:id="@+id/editText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:layout_marginStart="0dp"
        android:inputType="text"
        android:paddingEnd="0dp"
        android:paddingStart="0dp"
        android:text="EditText"
        android:textSize="20sp" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignStart="@id/editText"
        android:layout_below="@id/editText"
        android:layout_marginStart="0dp"
        android:layout_marginTop="16dp"
        android:paddingEnd="0dp"
        android:paddingStart="0dp"
        android:text="TextView"
        android:textSize="20sp"
        android:textStyle="bold" />

</RelativeLayout>