實現TextView文本顏色漸變的騷操做

前言

最近開發過程當中要實現文本顏色漸變的效果。什麼,文本顏色也要漸變?雖然不樂意,可是也只能說好吧...java

先來點最終效果圖 android

在這裏插入圖片描述
在這裏插入圖片描述

常規操做

常見的漸變作法有兩種,原理其實都是同樣的。都是建立一個 LinearGradient 對象,並將其設置到 TextView 的畫筆中。app

先來簡單介紹下 LinearGradientide

LinearGradient

Shader 子類,用於實現線性漸變的效果。經常使用的構造方法以下測試

public LinearGradient(float x0, float y0, float x1, float y1, int color0, int color1, Shader.TileMode tile) 複製代碼

參數說明ui

  • (x0, y0):漸變起始點座標
  • (x1, y1):漸變結束點座標
  • color0:漸變起始顏色
  • color1:漸變終止顏色
  • tile:填充模式
    • CLAMP:邊緣拉伸。使用邊緣顏色對區域外的範圍進行填充
    • REPEAT:重複模式。在水平和垂直兩個方向上重複填充
    • MIRROR:鏡像模式。在水平和垂直兩個方向上以鏡像的方式重複填充,相鄰圖像間有間隙

作法一

繼承 TextView,重寫 onLayout 方法後設置 Shaderthis

public class GradientTextView extends TextView {
	...
    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        if (changed) {
            getPaint().setShader(new LinearGradient(0, 0, getWidth(), getHeight(),
                    startColor,
                    endColor,
                    Shader.TileMode.CLAMP));
        }
    }
}
複製代碼

建立 LinearGradient 時,傳入的起始座標爲 (0,0),結束座標爲 (getWidth(), getHeight()),因此漸變效果是從左上角向右下角漸變的。效果以下 spa

在這裏插入圖片描述
也能夠改爲從上往下漸變的效果

getPaint().setShader(new LinearGradient(0, 0, 0, getHeight(),
                    startColor,
                    endColor,
                    Shader.TileMode.CLAMP));
複製代碼

效果以下 3d

在這裏插入圖片描述
這種作法是爲了獲取 View 的寬或高做爲 LinearGradient 的構造參數。若是漸變效果與 View 的寬或高無關,則無需使用此作法。另外此作法的漸變效果是總體的。若是想要實現 TextView 中每一行文本都漸變的話,能夠參考下面的作法二

作法二

直接設置 Shadercode

Shader shader = new LinearGradient(0, 0, 0, textView.getLineHeight(),
	        Color.RED, Color.BLUE, Shader.TileMode.REPEAT);
	textView.getPaint().setShader(shader);
	textView.setText("哈嘍,benio\n哈嘍,benio\n哈嘍,benio");
複製代碼

效果以下

在這裏插入圖片描述
多行漸變,效果不錯。可是這種作法有一點缺陷,那就是全部文字都變成漸變色了。假設咱們只須要部分字符是漸變色的話,這種方式就不太合理了。特別是在一些使用了 Span 的場景下。

騷操做

要實現部分文字顏色不同的話,第一時間我想到的是 Span。先看下官方提供的 ForegroundColorSpan

public class ForegroundColorSpan extends CharacterStyle implements UpdateAppearance, ParcelableSpan {

    private final int mColor;

    public ForegroundColorSpan(@ColorInt int color) {
        mColor = color;
    }
	...

    /** * Updates the color of the TextPaint to the foreground color. */
    @Override
    public void updateDrawState(@NonNull TextPaint textPaint) {
    	// 就是這裏改了顏色
        textPaint.setColor(mColor);
    }
}
複製代碼

能夠看到,關鍵就是 updateDrawState() 方法。咱們能夠在該方法內實現想要的樣式。接下來咱們參考 ForegroundColorSpan 的作法,依照上面作法二的思路,實現一個漸變色的 Span

class LinearGradientForegroundSpan extends CharacterStyle implements UpdateAppearance {
    private int startColor;
    private int endColor;
    private int lineHeight;

    public LinearGradientForegroundSpan(int startColor, int endColor, int lineHeight) {
        this.startColor = startColor;
        this.endColor = endColor;
        this.lineHeight = lineHeight;
    }

    @Override
    public void updateDrawState(TextPaint tp) {
        tp.setShader(new LinearGradient(0, 0, 0, lineHeight,
                startColor, endColor, Shader.TileMode.REPEAT));
    }
}
複製代碼

測試代碼

SpannableString part1 = new SpannableString("哈嘍,");
	part1.setSpan(new LinearGradientForegroundSpan(Color.RED, Color.LTGRAY, textView.getLineHeight()),
	        0, part1.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
	SpannableStringBuilder sb = new SpannableStringBuilder();
	sb.append(part1);
	sb.append("benio\n");
	
	SpannableString part2 = new SpannableString("哈嘍,benio\n哈嘍,benio");
	part2.setSpan(new LinearGradientForegroundSpan(Color.RED, Color.LTGRAY, textView.getLineHeight()),
	        0, part2.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
	sb.append(part2);
	textView.setText(sb);
複製代碼

效果以下

在這裏插入圖片描述
若是還不能知足你的需求,能夠將 Shader 做爲參數傳入 Span 中

class ShaderForegroundSpan extends CharacterStyle implements UpdateAppearance {
    private Shader mShader;

    public ShaderForegroundSpan(Shader shader) {
        mShader = shader;
    }

    @Override
    public void updateDrawState(TextPaint tp) {
        tp.setShader(mShader);
    }
}
複製代碼

小結

文本顏色漸變的原理都是經過建立一個 LinearGradient 對象,而後其設置到 TextView 的畫筆中實現的。構造 LinearGradient 的參數不一樣,漸變效果也不同

  • 作法一:漸變效果與 View 的寬或高相關。適用於全部文本總體漸變的場景
  • 作法二:漸變效果與行相關,每行的漸變效果一致。適用於每行文本漸變效果一致的場景
  • 作法三:用 Span 來實現,適用於局部文本漸變,多行文本漸變的場景

參考

相關文章
相關標籤/搜索