Android开发过程中,对TextView会用得非常多,字体颜色渐变或增加很多色彩.

这里说三种渐变方式:

一、LinearGradient

 1)继承 TextView,重写 onLayout 方法后设置 Shader,也可再ondraw中处理

public class GradientTextView1 extends AppCompatTextView {
private int mStartColor;
private int mEndColor;
private boolean mBold;

public GradientTextView1(@NonNull Context context) {
this(context, null);
}

public GradientTextView1(@NonNull Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}

public GradientTextView1(@NonNull Context context, @Nullable AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}

private void init(@NonNull Context context, @Nullable AttributeSet attrs) {
TypedArray typedArray =
context.obtainStyledAttributes(attrs, R.styleable.GradientTextView);
if (typedArray == null) {
return;
}

mBold = typedArray.getBoolean(R.styleable.GradientTextView_gradient_bold,
false);
mStartColor =
typedArray.getColor(R.styleable.GradientTextView_gradient_start_color,
getResources().getColor(R.color.primary_color));
mEndColor =
typedArray.getColor(R.styleable.GradientTextView_gradient_end_color,
getResources().getColor(R.color.accent_color));
typedArray.recycle();
if (mBold) {
getPaint().setFakeBoldText(true);
}
}

@SuppressLint("DrawAllocation")
@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(),
mStartColor,
mEndColor,
Shader.TileMode.CLAMP));
}
}
}

二、自自定义工具方法,在代码中动态改变

public class TextViewUtil {
public static void setTextColorGradient(TextView textView, @ColorRes int startColor, @ColorRes int endColor) {
if (textView == null || textView.getContext() == null) {
return;
}
Context context = textView.getContext();
@ColorInt final int sc = context.getResources().getColor(startColor);
@ColorInt final int ec = context.getResources().getColor(endColor);
final float x = textView.getPaint().getTextSize() * textView.getText().length();
LinearGradient gradient = new LinearGradient(0, 0, x, 0, sc, ec, Shader.TileMode.CLAMP);
textView.getPaint().setShader(gradient);
textView.invalidate();
}

public static void setTextColorGradient(TextView textView, int[] colors, float[] positions) {
if (textView == null || textView.getContext() == null) {
return;
}

String text = textView.getText().toString();
// 方法1:getTextBounds
Rect rect = new Rect();
textView.getPaint().getTextBounds(text, 0, text.length(), rect);
// 方法2:measureText
// float measuredWidth = textView.getPaint().measureText(text);
float textWidth = rect.width();
LinearGradient linearGradient = new LinearGradient(0, 0, textWidth, 0,
colors,
positions,
Shader.TileMode.REPEAT);
textView.getPaint().setShader(linearGradient);
textView.invalidate();
}


public static void clearTextColorGradient(TextView textView) {
textView.getPaint().setShader(null);
textView.invalidate();
}

三、使用Span做法,自定义一个Span,自己写个Span,代码中再去用

使用这种方式:

<declare-styleable name="GradientTextView">
<attr name="gradient_text" format="string" />
<attr name="gradient_bold" format="boolean" />
<attr name="gradient_start_color" format="color" />
<attr name="gradient_end_color" format="color" />
</declare-styleable>

public class GradientTextView extends AppCompatTextView {
private String mGradientText;
private int mStartColor;
private int mEndColor;
private boolean mBold;

public GradientTextView(@NonNull Context context) {
this(context, null);
}

public GradientTextView(@NonNull Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}

public GradientTextView(@NonNull Context context, @Nullable AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}

private void init(@NonNull Context context, @Nullable AttributeSet attrs) {
TypedArray typedArray =
context.obtainStyledAttributes(attrs, R.styleable.GradientTextView);
if (typedArray == null) {
return;
}
mGradientText =
typedArray.getString(R.styleable.GradientTextView_gradient_text);
mBold = typedArray.getBoolean(R.styleable.GradientTextView_gradient_bold,
false);
mStartColor =
typedArray.getColor(R.styleable.GradientTextView_gradient_start_color,
getResources().getColor(R.color.primary_color));
mEndColor =
typedArray.getColor(R.styleable.GradientTextView_gradient_end_color,
getResources().getColor(R.color.accent_color));
typedArray.recycle();
setGradientText(mGradientText);
if (mBold) {
getPaint().setFakeBoldText(true);
}
}

public void setGradientText(String text) {
if (text == null || text.length() == 0) {
return;
}
SpannableString spannableString = new SpannableString(text);
GradientFontSpan gradientFontSpan = new GradientFontSpan(mStartColor, mEndColor);
spannableString.setSpan(gradientFontSpan, 0, text.length(),
Spanned.SPAN_INCLUSIVE_INCLUSIVE);
setText(spannableString);
invalidate();
}

public static class GradientFontSpan extends ReplacementSpan {
private int mSize;
private int mStartColor;
private int mEndColor;

public GradientFontSpan(int startColor, int endColor) {
mStartColor = startColor;
mEndColor = endColor;
}

public GradientFontSpan(Context context) {
mStartColor = context.getResources().getColor(R.color.primary_color);
mEndColor = context.getResources().getColor(R.color.accent_color);
}

@Override
public int getSize(@NonNull Paint paint, CharSequence text, int start, int end,
@Nullable Paint.FontMetricsInt fm) {
mSize = Math.round(paint.measureText(text, start, end));
Paint.FontMetricsInt metrics = paint.getFontMetricsInt();
if (fm != null) {
fm.top = metrics.top;
fm.ascent = metrics.ascent;
fm.descent = metrics.descent;
fm.bottom = metrics.bottom;
}
return mSize;
}

@Override
public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x,
int top, int y, int bottom, @NonNull Paint paint) {
LinearGradient gradient = new LinearGradient(0, 0, mSize, 0, mEndColor, mStartColor,
Shader.TileMode.CLAMP);
paint.setShader(gradient);
canvas.drawText(text, start, end, x, y, paint);
}
}
}

这三种方式都可以实现文本渐变效果

                                                                           - END