2017-04-25 39 views
1

編輯:我已經能夠跟蹤到使用EditText而不是TextView的問題。重複呼叫僅在字段爲EditText時發生,並且當字段爲TextView時系統會自行運行。我在文檔或在線中找不到任何內容,表明LineBackgroundSpan不適用於EditTextLineBackgroundSpan drawBackground()重複調用

我已更新MCVE以顯示事情如何與TextView(它)和EditText(它不 - 至少不是很好)一起工作。我更新的問題是如何獲得LineBackgroundSpanEditText一起使用。


我實現了一個簡單的類添加一個圓形的背景使用LineBackgroundSpanEditText爲文本。一切正常,但在調試過程中,我注意到我的類的方法被重複調用,看起來,即使沒有進行任何更改,字符串中的每個跨度都沒有結束。它在顯示屏上並不明顯,但如果在方法中設置了斷點,則顯而易見。

在試圖追蹤問題時,我能夠將代碼縮減爲MCVE。以下代碼將簡單地突出顯示整行文本。最上面一行是EditText,最後一行是TextView。 (這不是我真正想要做的,但它是有用的。)

此MCVE對運行API 17和API 24的仿真器以及運行API 24的實際電話展現了問題。設置disableDraw參數爲trueRoundedBackgroudSpan()的構造函數將在drawBackground()中禁用背景繪製操作。即使在禁用背景繪製的情況下,我也會在EditText上看到問題。

這是怎麼回事?我誤解了如何使用跨度?將跨越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; 
} 

activity_main.xml中

<?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> 
+0

您是否找到答案?多久它需要'EditText'?它可能與光標閃爍率有關嗎? – Suragch

+0

@Suragch我還沒有找到這個問題的答案。我剛回去檢查有多少個「drawBackground」調用。目前的計數是1,426,每秒增加約2倍。如果我在應用跨度之前清除所有跨度,則可以避免此問題,因此似乎存在導致此問題的基礎跨度交互。這是一個沉默的問題,在屏幕上或性能上並不明顯。我偶然發現它是因爲我在'drawBackground'中設置了一個斷點。至於光標眨眼率,光標隱藏在背景之後,而且我也沒有對速率做任何事情。 – Cheticamp

+0

@Sugarch我認爲你對光標閃爍率是正確的。這些呼叫是以閃爍的光標速率計時的。我認爲光標將與背景圖分開,但它看起來不是。如果您可以填寫答案,我會接受。謝謝! – Cheticamp

回答

1

drawBackground()該呼叫被定時以閃爍的光標的速度大約是500毫秒通過@所建議的Suragch。我現在確信,對drawBackground()的調用是作爲遊標實現的一部分。

作爲一個快速但不確定的測試,我已將EditText字段設置爲不顯示光標,但仍然是可編輯的(android:cursorVisible="false")。當此屬性設置爲false時,重複調用drawBackground()將停止。