概述

Android自定义view绘制颜色的时候,可以通过setShader可以让view绘制多彩渐变的效果。Android sdk中提供了五个Shader子类供开发者使用,分别是:LinearGradient线性渐变 SweetGradient角度渐变 RadialGradient辐射渐变 BitmapShader图片shader和ComposeShader组合着色器。本文将结合例子对线性渐变做一个介绍。

LinearGradient 线性渐变

构造函数参数说明

 public LinearGradient(float x0, float y0, float x1, float y1,            @ColorInt int color0, @ColorInt int color1,            @NonNull TileMode tile)

该构造函数前四个参数代码颜色渐变的起点(x0,y0)和结束点(x1,y1)参数color0与color1代表startColor和endColor。TitleModel 有三个值(CLAMP、MIRROR、REPEAT)代表渐变模式。
列子代码:

 public LinearGradient(float x0, float y0, float x1, float y1, @NonNull @ColorInt int colors[],            @Nullable float positions[], @NonNull TileMode tile)

该构造函数前四个参数代码颜色渐变的起点(x0,y0)和结束点(x1,y1)参数colors数组代表渐变过度颜色,positions数组代表各过度色的起点位置(浮点类型)。TitleModel 有三个值(CLAMP、MIRROR、REPEAT)代表渐变模式。

例子代码

package com.xol.widget;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.LinearGradient;import android.graphics.Paint;import android.graphics.RectF;import android.graphics.Shader;import android.support.annotation.Nullable;import android.util.AttributeSet;import android.view.View;import com.xol.util.CommonUtil;/** * Created by wwzhang on 2019/3/14 */public class LinearGradientView extends View {    private Paint mPaint;    private LinearGradient mLinearGradient;    private int mWidthNum = 3;    private int mHeightNum = 3;    private int[] colorThree;    private int[] colorTwo;    private int mSpace;    private float mWidth = 0;    private float mRectRadius = 5;    private String mContentText = "非淡泊无以明智,非宁静无以致远";    public LinearGradientView(Context context) {        super(context);    }    public LinearGradientView(Context context, @Nullable AttributeSet attrs) {        super(context, attrs);    }    public LinearGradientView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);    }    {        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);        mPaint.setStyle(Paint.Style.FILL);        mPaint.setTextSize(CommonUtil.sp2px(16, getContext()));        mRectRadius = CommonUtil.dp2px(mRectRadius, getContext());        colorThree = new int[]{                Color.parseColor("#ff0000"),                Color.parseColor("#00ff00"),                Color.parseColor("#0000ff")};        colorTwo = new int[]{Color.parseColor("#ff0000"),                Color.parseColor("#0000ff")};        mSpace = (int) CommonUtil.dp2px(2, getContext());        mPaint.setColor(Color.parseColor("#AAAAAA"));    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        drawLinearRound(canvas);    }    public void drawLinearRound(Canvas canvas) {        //绘制两色渐变        int rectHeight = (int) CommonUtil.dp2px(20, getContext());        int space = 10;        //水平clamp        mLinearGradient = new LinearGradient(0, 0, getMeasuredWidth() / 2,                0, colorTwo[0], colorTwo[1], Shader.TileMode.CLAMP);        mPaint.setShader(mLinearGradient);        canvas.drawRect(0, 0 + space, getMeasuredWidth(), rectHeight + space, mPaint);        // 水平mirror        mLinearGradient = new LinearGradient(0, 0, getMeasuredWidth() / 2,                0, colorTwo[0], colorTwo[1], Shader.TileMode.MIRROR);        mPaint.setShader(mLinearGradient);        canvas.drawRect(0, rectHeight + space * 2, getMeasuredWidth(),                (rectHeight << 1) + space * 2, mPaint);        //水平repeat        mLinearGradient = new LinearGradient(0, 0, getMeasuredWidth() / 2,                0, colorTwo[0], colorTwo[1], Shader.TileMode.REPEAT);        mPaint.setShader(mLinearGradient);        canvas.drawRect(0, (rectHeight << 1) + space * 3, getMeasuredWidth(),                (rectHeight << 1) + rectHeight + space * 3, mPaint);        //对角线mirror渐变        mLinearGradient = new LinearGradient(0, 0, 20, 20,                colorTwo[0], colorTwo[1], Shader.TileMode.MIRROR);        mPaint.setShader(mLinearGradient);        canvas.drawRect(0, (rectHeight << 1) + rectHeight + space * 4, getMeasuredWidth(),                (rectHeight << 2) + space * 4, mPaint);        //计算        if (mWidth < 5) {            mWidth = (getMeasuredWidth() - (mWidthNum + 1) * mSpace) / mWidthNum;            mHeightNum = (int) (getMeasuredHeight() - CommonUtil.dp2px(120, getContext()) / mWidth);        }        //绘制三色渐变        int count = 0;        RectF rectF = new RectF();        for (int i = 0; i < mHeightNum; i++) {            rectF.top = i * mWidth + (i + 1) * mSpace + (int) CommonUtil.dp2px(120, getContext());            rectF.bottom = rectF.top + mWidth;            for (int j = 0; j < mWidthNum; j++) {                rectF.left = j * mWidth + (j + 1) * mSpace;                rectF.right = rectF.left + mWidth;                count++;                if (count > 9) {                    break;                }                switch (count) {                    case 1:                        mLinearGradient = new LinearGradient(rectF.left, rectF.top,                                rectF.left + (rectF.right - rectF.left) / 2, rectF.top + (rectF.bottom - rectF.top) / 2, colorThree,                                new float[]{0.0f, 0.66f, 1.0f}, Shader.TileMode.REPEAT);                        mPaint.setShader(mLinearGradient);                        break;                    case 2:                        mLinearGradient = new LinearGradient(rectF.left, rectF.top,                                rectF.left + (rectF.right - rectF.left) / 2, rectF.top + (rectF.bottom - rectF.top) / 2, colorThree,                                new float[]{0.0f, 0.66f, 1.0f}, Shader.TileMode.MIRROR);                        mPaint.setShader(mLinearGradient);                        break;                    case 3:                        mLinearGradient = new LinearGradient(rectF.left, rectF.top,                                rectF.left + (rectF.right - rectF.left) / 2, rectF.top + (rectF.bottom - rectF.top) / 2, colorThree,                                new float[]{0.0f, 0.66f, 1.0f}, Shader.TileMode.CLAMP);                        mPaint.setShader(mLinearGradient);                        break;                    case 4:                        mLinearGradient = new LinearGradient(rectF.left, rectF.top,                                rectF.left + (rectF.right - rectF.left) / 2, rectF.top, colorThree,                                new float[]{0.0f, 0.66f, 1.0f}, Shader.TileMode.REPEAT);                        mPaint.setShader(mLinearGradient);                        break;                    case 5:                        mLinearGradient = new LinearGradient(rectF.left, rectF.top,                                rectF.left + (rectF.right - rectF.left) / 2, rectF.top, colorThree,                                new float[]{0.0f, 0.66f, 1.0f}, Shader.TileMode.MIRROR);                        mPaint.setShader(mLinearGradient);                        break;                    case 6:                        mLinearGradient = new LinearGradient(rectF.left, rectF.top,                                rectF.left + (rectF.right - rectF.left) / 2, rectF.top, colorThree,                                new float[]{0.0f, 0.66f, 1.0f}, Shader.TileMode.CLAMP);                        mPaint.setShader(mLinearGradient);                        break;                    case 7:                        mLinearGradient = new LinearGradient(rectF.left, rectF.top,                                rectF.right, rectF.bottom, colorThree,                                new float[]{0.0f, 0.66f, 1.0f}, Shader.TileMode.REPEAT);                        mPaint.setShader(mLinearGradient);                        break;                    case 8:                        mLinearGradient = new LinearGradient(rectF.left, rectF.bottom,                                rectF.right, rectF.bottom, colorThree,                                new float[]{0.0f, 0.66f, 1.0f}, Shader.TileMode.REPEAT);                        mPaint.setShader(mLinearGradient);                        break;                    case 9:                        mLinearGradient = new LinearGradient(rectF.left, rectF.bottom,                                rectF.right, rectF.bottom, colorThree,                                new float[]{0.5f, 0.75f, 1.0f}, Shader.TileMode.REPEAT);                        mPaint.setShader(mLinearGradient);                        break;                    default:                        break;                }                canvas.drawRoundRect(rectF, mRectRadius, mRectRadius, mPaint);            }        }    }}

布局文件引入

<?xml version="1.0" encoding="utf-8"?>    

运行结果:

线性渐变文字效果实现

闪动的文字

实现原理,通过matrix水平移动线性shader开始的位置,达到文字闪动的效果

歌词逐字变色效果

实现原理,通过设置线性shader的变色位置,实现文字的逐渐变色。
示例代码:

package com.xol.widget;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.LinearGradient;import android.graphics.Matrix;import android.graphics.Paint;import android.graphics.Rect;import android.graphics.Shader;import android.support.annotation.Nullable;import android.util.AttributeSet;import android.view.View;import com.xol.util.CommonUtil;/** * Created by wwzhang on 2019/3/18 */public class LinearGradientTextView extends View implements Runnable {    private Paint mPaint;    private Matrix mMatrix;    private String mText;    private LinearGradient mLinearGradient;    private long mDuration = 50;    private int mTransX = 0;    private Rect rect = new Rect();    private LinearGradient mKrcLinearGradient;    private float[] mfKrc = new float[2];    private String mSingText;    private Paint mSingPaint;    public LinearGradientTextView(Context context) {        super(context);    }    public LinearGradientTextView(Context context, @Nullable AttributeSet attrs) {        super(context, attrs);    }    public LinearGradientTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);    }    {        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);        mSingPaint = new Paint(Paint.ANTI_ALIAS_FLAG);        mMatrix = new Matrix();        mText = "疏疏晴雨弄斜阳,凭栏久,墙外杏花香";        mSingText = "很爱很爱你所以愿意,不牵绊你";        mPaint.setTextSize(CommonUtil.dp2px(16, getContext()));        mSingPaint.setTextSize(CommonUtil.dp2px(16, getContext()));    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        if (null == mLinearGradient) {            mLinearGradient = new LinearGradient(0, 0, 200, 0,                    new int[]{Color.parseColor("#440000"),                            Color.parseColor("#ffffff"),                            Color.parseColor("#440000")},                    new float[]{0.0f, 0.5f, 1.0f}, Shader.TileMode.CLAMP);            mLinearGradient.setLocalMatrix(mMatrix);            mPaint.setShader(mLinearGradient);            mfKrc[0] = 0.0f;            mfKrc[1] = 0.0f;            mKrcLinearGradient = new LinearGradient(0, 0, getMeasuredWidth(), 0, new int[]{                    Color.parseColor("#ff0000"),                    Color.parseColor("#ffffff")},                    mfKrc,                    Shader.TileMode.CLAMP);            mSingPaint.setShader(mKrcLinearGradient);            postDelayed(this, mDuration);        }        mPaint.getTextBounds(mText, 0, mText.length(), rect);        canvas.drawText(mText, 0, rect.bottom - rect.top, mPaint);        canvas.drawText(mSingText, 0, getMeasuredHeight() / 2, mSingPaint);    }    @Override    public void run() {        mTransX += 10;        if (mTransX > rect.right - rect.left) {            mTransX = -10;        }        mfKrc[0] += 0.01f;        mfKrc[1] = mfKrc[0];        if (mfKrc[0] > 1.0f) {            mfKrc[0] = 0.0f;            mfKrc[1] = 0.0f;        }        mKrcLinearGradient = new LinearGradient(0, 0, getMeasuredWidth(), 0, new int[]{                Color.parseColor("#ff0000"),                Color.parseColor("#ffffff")},                mfKrc,                Shader.TileMode.CLAMP);        mSingPaint.setShader(mKrcLinearGradient);        mMatrix.setTranslate(mTransX, 0);        mLinearGradient.setLocalMatrix(mMatrix);        invalidate();        postDelayed(this, mDuration);    }}

布局文件

<?xml version="1.0" encoding="utf-8"?>        

代码运行效果


希望对您有所帮助!

更多相关文章

  1. android framework 源码流程分析技巧
  2. Android(安卓)Material Design动画 Reveal Effect | 揭示效果
  3. Android自定义action与permission
  4. Android(安卓)IPC之ContentProvider和Socket(Android开发艺术探索
  5. Android(安卓)在webview中设置代理
  6. android webview用法小结2 java与javascript的交互
  7. 推荐Android15个常用的图表库,包含线性,条形柱状,饼状图,扇形,雷达,股
  8. Android中的工厂模式(减少if-else和switch-case)
  9. [置顶] 100多个Android(安卓)Demo的整合

随机推荐

  1. Android(安卓)scrollview里面放listview
  2. 【Android(安卓)开发教程】AnalogClock和
  3. Android数据过滤器:Filter
  4. Android使用WebView加载网页选择文件上传
  5. Android(java)学习笔记104:Map集合的遍历之
  6. Android(安卓)Audio 创建AudioTrack对象
  7. achartengine之折线图---简单用法
  8. Android实现单页显示3个Item的ViewPager
  9. actionbar 详解教程
  10. android发送