Android Paint关于Shader

前言

Paint作为自定义View中常用的类,对颜色的绘制可以分为三层

  • paint颜色设置
    • paint.setAlpha(0x20);
    • paint.setColor(Color.parseColor("#1b8fe6"));
    • paint.setARGB(0xff, 0xff, 0xff, 0x00);
    • paint.setShader(new XXShader());着色器的优先级要高于前面颜色的设置
  • 滤镜的设置
    • paint.setColorFilter(new XXFilter());
  • paint.setXfermode(Xfermode xfermode);Xfermode 指的是你要绘制的内容和 Canvas 的目标位置的内容应该怎样结合计算出最终的颜色。但通俗地说,其实就是要你以绘制的内容作为源图像,以 View 中已有的内容作为目标图像,选取一个 PorterDuff.Mode 作为绘制内容的颜色处理方案

TileMode

在讲解Shader的子类之前,我们先来看看TileMode这个枚举

public enum TileMode {

    CLAMP   (0),
 
    REPEAT  (1),

    MIRROR  (2);

}
  • CLAMP表示剩余部分保持最终的颜色
  • REPEAT表示剩余部分重新开始渐变
  • MIRRO表示剩余部分和渐变部分成镜像对称

Shader的分类

Shader着色器分为如下5类

  • 渐变系列
    • LinearGradient 线性渐变
    • SweepGradient 角度渐变
    • RadialGradient 辐射渐变
  • BitmapShader
  • ComposeShader

LinearGradient

线性渐变,我反手就是一段代码

    protected void onDraw(Canvas canvas) {

        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setStrokeWidth(50);

        paint.setShader(new LinearGradient(50, 50, 500, 50, Color.RED, Color.YELLOW,
                Shader.TileMode.CLAMP));

        canvas.drawLine(50, 50, 700, 50, paint);

    }

表示从(x1,y1)到(x2,y2),从startColor渐变到endColor,TileMode就是前面说的渐变模式,这里为默认的CLAMP,所以从x轴的500往后都是保持YELLOW,效果图如下所示

LinearGradient.png

SweepGradient

角度渐变,我反手又是一段代码。默认是从3点钟方向(0度)位置开始顺时针渐变360度

    protected void onDraw(Canvas canvas) {

        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setStrokeWidth(50);

        paint.setShader(new SweepGradient(200, 200, Color.RED, Color.YELLOW));

        canvas.drawCircle(200, 200, 100, paint);

    }

表示从(x,y)点为圆心,从startColor渐变到endColor。效果图如下所示

Android Paint关于Shader_第1张图片
SweepGradient.png

RadialGradient

辐射渐变,是一种扩散的渐变效果,我反手再来一段代码

    protected void onDraw(Canvas canvas) {

        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setStrokeWidth(50);

        paint.setShader(new RadialGradient(200, 200, 50, Color.RED, Color.YELLOW,
                Shader.TileMode.MIRROR));

        canvas.drawCircle(200, 200, 100, paint);

    }

表示以(x,y)为圆心,以radius为辐射半径,从startColor渐变到endColor,渐变模式是MIRROR。效果图如下所示

Android Paint关于Shader_第2张图片
RadialGradient.png

BitmapShader

我反手再来一段代码

    protected void onDraw(Canvas canvas) {

        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setStrokeWidth(50);

        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher_round);

        paint.setShader(new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT));

        canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), paint);

    }

效果图如下所示

Android Paint关于Shader_第3张图片
BitmapShader.png

ComposeShader

这里我们使用两个BitmapShader,最后再甩一段代码

    protected void onDraw(Canvas canvas) {

        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setStrokeWidth(50);

        Bitmap b1 = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher_round);
        Shader s1 = new BitmapShader(b1, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);

        Bitmap b2 = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher_foreground);
        Shader s2 = new BitmapShader(b2, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);

        paint.setShader(new ComposeShader(s1, s2, PorterDuff.Mode.DST_IN));

        canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), paint);

    }

兴高采烈的看了下运行结果,发现手机上是空白的。注意,ComposeShader在硬件加速的情况下是不支持两个相同的Shader,所以我们得关闭硬件加速

setLayerType(LAYER_TYPE_SOFTWARE, null);

如果不明白PorterDuff.Mode的,可以看看之前写的这一篇文章PorterDuff.Mode;DST_IN表示绘制目标图像的重叠部分,效果图如下,图片选取的不好。

Android Paint关于Shader_第4张图片
ComposeShader.png

你可能感兴趣的:(Android Paint关于Shader)