2012-01-26 67 views
0

我有一堆文本可能太長以至於無法放在用戶的屏幕上。因此,我不想浪費空間,而僅僅顯示一小段摘要並允許用戶展開它。此功能的設計需要在該摘錄末尾添加一小段彩色文本(「Show More ...」)。根據文本狀態更改TextView中某段文本的顏色

我想知道如何我可以:

  • 彩色文本的位不同的顏色比文本的其餘部分。
  • 根據TextTiew的狀態更改該位文本的顏色。藍色,如果用戶沒有與它互動,並在用戶按下時呈紅色。

這是可能的,我將如何去做呢?

注意:在某種意義上,我將把整個TextView作爲一個按鈕連接起來。

回答

2

您可以覆蓋ellipsize行爲就像我已經做了延長的TextView(基於這個問題代碼:android ellipsize multiline textview

import android.content.Context; 
import android.graphics.Canvas; 
import android.text.Layout; 
import android.text.Layout.Alignment; 
import android.text.SpannableStringBuilder; 
import android.text.StaticLayout; 
import android.text.TextUtils; 
import android.text.TextUtils.TruncateAt; 
import android.util.AttributeSet; 
import android.widget.TextView; 

import java.util.ArrayList; 
import java.util.List; 


public class EllipsizingTextView extends TextView { 
    private static final char ELLIPSIS = '…'; 

    public interface EllipsizeListener { 
     void ellipsizeStateChanged(boolean ellipsized); 
    } 

    private final List<EllipsizeListener> ellipsizeListeners = new ArrayList<EllipsizeListener>(); 
    private volatile boolean isEllipsized; 
    private volatile boolean isStale; 
    private volatile boolean programmaticChange; 
    private CharSequence fullCharSequence; 
    private int maxLines = -1; 
    private float lineSpacingMultiplier = 1.0f; 
    private float lineAdditionalVerticalPadding = 0.0f; 

    public EllipsizingTextView(Context context) { 
     super(context); 
    } 

    public EllipsizingTextView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     initAttributes(context, attrs); 
    } 

    public EllipsizingTextView(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
     initAttributes(context, attrs); 
    } 

    private void initAttributes(Context context, AttributeSet attrs) { 
     maxLines = attrs.getAttributeIntValue("http://schemas.android.com/apk/res/android", "maxLines", -1); 
     if (maxLines != -1) { 
      isStale = true; 
     } 
    } 

    public void addEllipsizeListener(EllipsizeListener listener) { 
     if (listener == null) { 
      throw new NullPointerException(); 
     } 
     ellipsizeListeners.add(listener); 
    } 

    public void removeEllipsizeListener(EllipsizeListener listener) { 
     ellipsizeListeners.remove(listener); 
    } 

    public boolean isEllipsized() { 
     return isEllipsized; 
    } 

    public void setMaxLines(int maxLines) { 
     if (getMaxLines() != maxLines) { 
      super.setMaxLines(maxLines); 
      this.maxLines = maxLines; 
      isStale = true; 
     } 
    } 

    public int getMaxLines() { 
     return maxLines; 
    } 

    public void setLineSpacing(float add, float mult) { 
     this.lineAdditionalVerticalPadding = add; 
     this.lineSpacingMultiplier = mult; 
     super.setLineSpacing(add, mult); 
    } 

    protected void onTextChanged(CharSequence text, int start, int before, int after) { 
     super.onTextChanged(text, start, before, after); 
     if (!programmaticChange) { 
      fullCharSequence = text; 
      isStale = true; 
     } 
    } 

    protected void onDraw(Canvas canvas) { 
     if (isStale) { 
      super.setEllipsize(null); 
      resetText(); 
     } 
     super.onDraw(canvas); 
    } 

    private void resetText() { 
     int maxLines = getMaxLines(); 
     boolean ellipsized = false; 
     SpannableStringBuilder builder = SpannableStringBuilder.valueOf(fullCharSequence); 

     if (maxLines != -1) { 
      Layout layout = createWorkingLayout(builder); 
      if (layout.getLineCount() > maxLines) { 
       int end = layout.getLineEnd(maxLines - 1); 
       int nextSpace = builder.toString().indexOf(' ', end); 
       if (nextSpace != -1) { 
        builder.delete(end, builder.length()); 
       } 
       builder.append(ELLIPSIS); 
       while (createWorkingLayout(builder).getLineCount() > maxLines) { 
        int pos = builder.toString().lastIndexOf(' '); 
        builder.delete(pos, builder.length()); 
        builder.append(ELLIPSIS); 
       } 
       ellipsized = true; 
      } 
     } 

     if (!TextUtils.equals(builder, getText())) { 
      programmaticChange = true; 
      try { 
       setText(builder); 
      } finally { 
       programmaticChange = false; 
      } 
     } 
     isStale = false; 
     if (ellipsized != isEllipsized) { 
      isEllipsized = ellipsized; 
      for (EllipsizeListener listener : ellipsizeListeners) { 
       listener.ellipsizeStateChanged(ellipsized); 
      } 
     } 
    } 

    private Layout createWorkingLayout(CharSequence workingText) { 
     return new StaticLayout(workingText, getPaint(), getWidth() - getPaddingLeft() - getPaddingRight(), 
       Alignment.ALIGN_NORMAL, lineSpacingMultiplier, lineAdditionalVerticalPadding, false); 
    } 

    public void setEllipsize(TruncateAt where) { 
     // Ellipsize settings are not respected 
    } 

    public int getLineCount() { 
     return Math.min(super.getLineCount(), getMaxLines()); 
    } 

    protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 
     if (changed) { 
      isStale = true; 
     } 
     super.onLayout(changed, left, top, right, bottom); 
    } 
} 

您可以用字符串替換省略號(如「顯示更多」),並添加ForegroundColorSpan或BackgroundColorSpan用於這部分文本。在這種情況下請小心空格(它可能導致你無限循環)。

+0

運行完美。謝謝。但是由於使用了builder.toString(),它忽略了所有的spannables。我不得不刪除toString()並使用CharSequence中的indexOf(我使用Kotlin)來使用spannables。 – muthuraj

0

fromHTML方法可以實現一個textview中不同顏色的文本。 和觸摸狀態的用戶反饋可以通過onTouchListener設置爲textview來實現。 但在onTouchListener中,您將需要編碼來更改文字顏色。

相關問題