Android LinearGradient的使用

概述

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"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.xol.widget.LinearGradientView
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</FrameLayout>

运行结果:

线性渐变文字效果实现

闪动的文字

实现原理,通过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"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    

    <com.xol.widget.LinearGradientTextView
        android:background="#888888"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</FrameLayout>

代码运行效果

在这里插入图片描述
希望对您有所帮助!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章