Android(安卓)LinearGradient的使用
16lz
2021-01-26
概述
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"?>
代码运行效果
希望对您有所帮助!
更多相关文章
- android framework 源码流程分析技巧
- Android(安卓)Material Design动画 Reveal Effect | 揭示效果
- Android自定义action与permission
- Android(安卓)IPC之ContentProvider和Socket(Android开发艺术探索
- Android(安卓)在webview中设置代理
- android webview用法小结2 java与javascript的交互
- 推荐Android15个常用的图表库,包含线性,条形柱状,饼状图,扇形,雷达,股
- Android中的工厂模式(减少if-else和switch-case)
- [置顶] 100多个Android(安卓)Demo的整合