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>

代碼運行效果

在這裏插入圖片描述
希望對您有所幫助!

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