自定义渐变TextView

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.RadialGradient;
import android.graphics.Shader;
import android.graphics.SweepGradient;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.widget.TextView;

/*
 *  @文件名:   ShaderTextView
 *  @创建者:   cai
 *  @创建时间:  2018/3/29 17:14
 *  @描述:    渐变TextView

    TileMode:(一共有三种)
    CLAMP:如果渲染器超出原始边界范围,会复制范围内边缘染色(拉伸的是图片最后的那一个像素,并不断重复)。
    REPEAT:横向和纵向的重复渲染器图片,平铺(横向 纵向不断重复)。
    MIRROR:横向和纵向的重复渲染器图片,这个和REPEAT重复方式不一样,他是以镜像方式平铺(横向纵向不断翻转重复)

    RadialGradient:用来进行环形渲染
    SweepGradient:扫描渐变—围绕一个中心点扫描渐变就像电影里那种雷达扫描,用来梯度渲染。
    ComposeShader:组合渲染,可以和其他几个子类组合起来使用;
 */
public class ShaderTextView
        extends TextView {
    private static final String TAG = "ShadeTextView";

    //动画类型
    public static final int MOEV_ANIM_TYPE   = 1;
    public static final int ROTATE_ANIM_TYPE = 2;
    public static final int CUSTOM_ANIM_TYPE = 3;

    //渐变类型
    public static final int LINEAR_GRADIENT_TYPE = 11;
    public static final int RADIAL_GRADIENT_TYPE = 22;
    public static final int SWEEP_GRADIENT_TYPE  = 33;

    private CustomAnimInterface mAnimInterface;

    /** 移动距离*/
    private int    translateWidth;
    private Paint  paint;
    private Matrix matrix;

    private Shader mShader = getDefaultLinearGradient();
    private int    mHeight;
    private int    mWidth;
    private boolean isPlay = false;
    private float mDegrees;
    private int animType   = MOEV_ANIM_TYPE;

    public boolean isLock() {
        return lock;
    }

    public void setLock(boolean lock) {
        this.lock = lock;
    }

    private boolean lock = true;


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

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

    public ShaderTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        if (!lock){
            mWidth = getMeasuredWidth();
            paint = getPaint();
            //添加渲染
            paint.setShader(mShader);
            paint.setColor(Color.BLACK);
        }
    }

    public void setShader(Shader shader){
        mShader = shader;
    }

    /**
     * 设置渲染方式
     * @param type {@link #LINEAR_GRADIENT_TYPE},{@link #RADIAL_GRADIENT_TYPE},{@link #SWEEP_GRADIENT_TYPE}
     */
    public void setShader(int type) {
        switch (type) {
            case LINEAR_GRADIENT_TYPE:
                mShader = getDefaultLinearGradient();
                break;
            case RADIAL_GRADIENT_TYPE:
                mShader = getDefaultRadialGradient();
                break;
            case SWEEP_GRADIENT_TYPE:
                mShader = getDefaultSweepGradient();
                break;
            default:
                mShader = getDefaultLinearGradient();
                break;
        }
        requestLayout();
    }

    @NonNull
    public LinearGradient getDefaultLinearGradient() {
        measure(0,0);
        mWidth = getMeasuredWidth();
        mHeight = getMeasuredHeight();
        return new LinearGradient(0,
                                  0,
                                  mWidth,
                                  mHeight,
                                  new int[]{Color.RED,
                                            Color.GREEN,
                                            Color.MAGENTA},
                                  new float[]{0,
                                              0.5f,
                                              1f},
                                  Shader.TileMode.MIRROR);
    }

    @NonNull
    public RadialGradient getDefaultRadialGradient() {
        measure(0,0);
        mWidth = getMeasuredWidth();
        mHeight = getMeasuredHeight();
        float radius = mWidth / 2.0f;
        if (mHeight > mWidth) {
            radius = mHeight / 2.0f;
        }
        return new RadialGradient(mWidth / 2,
                                  mHeight / 2,
                                  radius,
                                  new int[]{Color.RED,
                                            Color.GREEN,
                                            Color.MAGENTA},
                                  new float[]{0,
                                              0.5f,
                                              1f},
                                  Shader.TileMode.MIRROR);
    }

    @NonNull
    public SweepGradient getDefaultSweepGradient() {
        measure(0,0);
        mWidth = getMeasuredWidth();
        mHeight = getMeasuredHeight();
        return new SweepGradient(mWidth / 2,
                                 mHeight / 2,
                                 new int[]{Color.RED,
                                           Color.GREEN,
                                           Color.MAGENTA},
                                 new float[]{0,
                                             0.5f,
                                             1f});
    }

    public void setPlay(boolean play){
        setPlay(play,MOEV_ANIM_TYPE);
    }

    public void setPlay(int animType){
        setPlay(true,animType);
    }

    /**
     * 设置是否播放动画以及动画类型
     * @param play
     * @param animType 当animType=={@link #CUSTOM_ANIM_TYPE}时,
     *                 即采用自定义动画时,需实现接口{@link ShaderTextView.CustomAnimInterface},
     *                 并重写{@link ShaderTextView.CustomAnimInterface#customAnim(Matrix matrix,Shader shader)}方法
     */
    public void setPlay(boolean play, int animType) {
        isPlay = play;
        matrix = new Matrix();
        this.animType = animType;
        invalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (isPlay) {
            switch (animType) {
                case MOEV_ANIM_TYPE:
                    moveAnim();
                    break;
                case ROTATE_ANIM_TYPE:
                    rotateAnim();
                    break;
                case CUSTOM_ANIM_TYPE:
                    mAnimInterface.customAnim(matrix,mShader);
                    break;
                default:
                    moveAnim();
                    break;
            }
        }
    }

    private void moveAnim() {
        if (matrix == null) { return; }
        translateWidth += mWidth / 10;
        //表示刚刚移动 了width个宽度 即 正好包含了整个textview 的时候还原
        if (translateWidth > mWidth * 2) {
            translateWidth -= mWidth * 2;
        }
        //移动
        matrix.setTranslate(translateWidth, 0);
        mShader.setLocalMatrix(matrix);
        postInvalidateDelayed(100);
    }

    private void rotateAnim() {
        if (matrix == null) { return; }
        mDegrees += 15;
        //旋转
        matrix.setRotate(mDegrees, mWidth / 2f, mHeight / 2f);
        mShader.setLocalMatrix(matrix);
        postInvalidateDelayed(100);
    }

    public void setAnimInterface(CustomAnimInterface animInterface) {
        mAnimInterface = animInterface;
    }

    public static interface CustomAnimInterface{
        /**
         * 自定义动画
         * @param matrix
         */
        void customAnim(Matrix matrix,Shader shader);
    }

}

猜你喜欢

转载自blog.csdn.net/tomcat0916/article/details/79745808