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

 

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐