Android 自定义 View进阶 - Shader

本文详细介绍了Android中Shader的使用,包括Shader的子类LinearGradient、BitmapShader、SweepGradient、RadialGradient和ComposeShader。通过实例展示了如何创建渐变效果,如仿iOS滑动解锁动画、圆形图片、扫描效果和水波纹效果,以及如何组合不同Shader实现复杂动画。同时,提供了源码链接供进一步学习。
摘要由CSDN通过智能技术生成

不知曾几何时,渐变色变得流行起来了,各大手机厂商都发布了各自的渐变色手机,同时越来越多的 App ,也开始应用了渐变色的设计。为了满足工作需要,我们也要学习下 Android 中的渐变着色器 Shader。

效果图

Shader 介绍

Shader 单词为 着色器,在 Android 中的文档解释为:

Shader is the based class for objects that return horizontal spans of colors during drawing. A subclass of Shader is installed in a Paint calling paint.setShader(shader). After that any object (other than a bitmap) that is drawn with that paint will get its color(s) from the shader

着色器是在绘制过程中返回水平颜色范围的对象的基类。 Shader的子类安装在Paint中,调用paint.setShader(着色器)之后,使用该绘制绘制的任何对象(位图除外)都将从着色器中获取其颜色

Shader 相关类:

在这里插入图片描述

可以看出: Shader 有五个子类

  • BitmapShader 位图渲染
  • ComposeShader 组合渲染
  • LinearGradient 线性渲染
  • SweepGradient 梯度渲染
  • RadialGradient 光束渲染
Shader 用法

(1)调用 Shader 子类对象的构造方法创建着色器,设定 渲染模式。

// 创建线性着色器
linearGradient = new LinearGradient(0, 0, mViewWidth, 0,
                new int[]{
   Color.RED, Color.GREEN, Color.BLUE, Color.YELLOW},
                new float[]{
   0.2f, 0.5f, 0.8f, 0.9f},
                Shader.TileMode.REPEAT);

其中渲染模式 TileMode 有:

  • CLAMP 边缘拉伸模式,他会拉伸边缘的一个像素来填充其他区域。
  • REPEAT 重复模式,水平和垂直重复着色器的图像
  • MIRROR 镜像模式,水平和垂直重复着色器的图像,交替镜像,使相邻的图像始终接缝

(2)给画笔设置 Shader 着色器

// 为画笔设置渐变渲染器
paint.setShader(linearGradient);

(3)在 onDraw() 方法中使用 paint 进行绘制。

canvas.drawRect(rectF, paint);
LinearGradient

LinearGradient 构造方法:

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

上面一个构造函数很好理解,(x0,y0),(x1,y1) 分别表示起点和终点的坐标,颜色从 color0 到 color1 线性变化;

下面一个构造函数参数有点不好理解了。我们先看下使用这个构造函数后的效果:

在这里插入图片描述

/**
 * 线性渐变
 */
public class LinearGradientView extends View {
   

    private Paint paint;
    private Paint linePaint;
    private LinearGradient linearGradient;
    private int mViewWidth;
    private int mViewHeight;
    private RectF rectF;

    public LinearGradientView(Context context) {
   
        super(context);
        init();
    }

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

    private void init() {
   
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        linePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        linePaint.setStrokeWidth(DensityUtil.dp2Px(getContext(), 2));
        linePaint.setStyle(Paint.Style.FILL);
        linePaint.setColor(Color.BLACK);
        linePaint.setTextSize(DensityUtil.dp2Px(getContext(), 14));
        linePaint.setTextAlign(Paint.Align.CENTER);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
   
        super.onSizeChanged(w, h, oldw, oldh);
        mViewWidth = w;
        mViewHeight = h;

        rectF = new RectF(0, 0, mViewWidth, mViewHeight);
        /**
         * 渐变范围为 左上角顶点 (0,0) -> 右上角顶点 (mViewWidth,0) ,
         * 超出这个范围以 Shader.TileMode.REPEAT 重复的形式填充, 颜色渐变的方向为 水平方向,
         *
         *
         * 如果渐变范围:  (0,0) -> (mViewWidth,mViewHeight), 则 渐变方向为 对角线方向
         */
        linearGradient = new LinearGradient(0, 0, mViewWidth, 0,
                new int[]{
   Color.RED, Color.GREEN, Color.BLUE, Color.YELLOW},
                new float[]{
   0.2f, 0.5f, 0.8f, 0.9f},
                Shader.TileMode.REPEAT);
        paint.setShader(linearGradient);

    }

    @Override
    protected void onDraw(Canvas canvas) {
   
        super.onDraw(canvas);
        canvas.drawRect(rectF, paint);
        for (int i = 0; i <= 10; i++) {
   
            canvas.drawLine(rectF.width() * i * 0.1f, rectF.bottom, rectF.width() * i * 0.1f, rectF.bottom - 20, linePaint);
            canvas.drawText(String.valueOf(i / 10f), rectF.width() *
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值