Android绘制:Shader

shader中文意思着色器,「着色器」不是 Android 独有的,它是图形领域里一个通用的概念,它和直接设置颜色的区别是,着色器设置的是一个颜色方案,或者说是一套着色规则。当设置了 Shader 之后,Paint 在绘制图形和文字时就不使用 setColor/ARGB() 设置的颜色了,而是使用 Shader 的方案中的颜色。

LinearGradient 线性渐变

可以设置两个端点和两个端点的颜色,从而使用这两种颜色的渐变来绘制颜色:
构造方法: LinearGradient(float x0, float y0, float x1, float y1, int color0, int color1, Shader.TileMode tile)。

Shader shader = new LinearGradient(100,100,500,500, Color.parseColor("#E91E63"),Color.parseColor("#2196F3"), Shader.TileMode.CLAMP);
        paint.setShader(shader);
        canvas.drawCircle(300,300,200,paint);

Shader.TileMode

Shader的模型共有3个值

CLAMP

翻译为夹紧模式,会在端点之外延续端点处的颜色
看了下面的效果,就能理解。其实就是从在两个端点简渐变。

Android绘制:Shader_第1张图片
image.png
MIRROR

镜像模式
跟照镜子一样有个反的区域

Android绘制:Shader_第2张图片
image.png
REPEAT

重复模式
如名字一样

Android绘制:Shader_第3张图片
image.png

RadialGradient 辐射渐变

就是从中心向四周沿着半径渐变,翻译为辐射渐变

构造方法: RadialGradient(float centerX, float centerY, float radius, int centerColor, int edgeColor, TileMode tileMode)

参数: centerX centerY:辐射中心的坐标 radius:辐射半径 centerColor:辐射中心的颜色 edgeColor:辐射边缘的颜色 tileMode:辐射范围之外的着色模式。

 Shader shader = new RadialGradient(300, 300, 200, Color.parseColor("#E91E63"),
                Color.parseColor("#2196F3"), Shader.TileMode.MIRROR);
        paint.setShader(shader);
        canvas.drawCircle(300,300,200,paint);
Android绘制:Shader_第4张图片
image.png

我们在设置的时候注意radius和TileMode。
如果Shader中的centerX、 centerY、radius三个参数与
canvas.drawCircle中的前三个参数一致的话,那么不管你怎么设置tileMode,效果都是一样的。都是上面的效果

只有当radius这个参数小于显示半径之后TitleMode才有效果:
我们将上面代码中的radius改成40,TileMode:CLMP

 Shader shader = new RadialGradient(300, 300, 40, Color.parseColor("#E91E63"),
                Color.parseColor("#2196F3"), Shader.TileMode.CLAMP);
        paint.setShader(shader);
        canvas.drawCircle(300,300,200,paint);
Android绘制:Shader_第5张图片
image.png

再将TileMode改为MIRROR

Android绘制:Shader_第6张图片
image.png

再将TileMode改为REPEAT

Android绘制:Shader_第7张图片
image.png

对比这三个效果,再结合上面介绍的,大家估计就能理解三种模式了。

SweepGradient 扫描渐变

构造方法: SweepGradient(float cx, float cy, int color0, int color1)

参数: cx cy :扫描的中心 color0:扫描的起始颜色 color1:扫描的终止颜色

 Shader shader = new SweepGradient(300, 300, Color.parseColor("#E91E63"),
                Color.parseColor("#2196F3"));
        paint.setShader(shader);
        canvas.drawCircle(300, 300, 200, paint);
Android绘制:Shader_第8张图片
image.png

BitmapShader

用 Bitmap 来着色,用 Bitmap 的像素来作为图形或文字的填充。

Android绘制:Shader_第9张图片
image.png

构造方法: BitmapShader(Bitmap bitmap, Shader.TileMode tileX, Shader.TileMode tileY)

参数: bitmap:用来做模板的 Bitmap 对象 tileX:横向的 TileMode tileY:纵向的 TileMode。

 Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.mark_big);
        Shader shader = new BitmapShader(bitmap, Shader.TileMode.MIRROR, Shader.TileMode.MIRROR);
        paint.setShader(shader);

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

运行效果:

Android绘制:Shader_第10张图片
image.png

ComposeShader 混合着色器

// 第一个 Shader:头像的 Bitmap
Bitmap bitmap1 = BitmapFactory.decodeResource(getResources(), R.drawable.batman);  
Shader shader1 = new BitmapShader(bitmap1, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);

// 第二个 Shader:从上到下的线性渐变(由透明到黑色)
Bitmap bitmap2 = BitmapFactory.decodeResource(getResources(), R.drawable.batman_logo);  
Shader shader2 = new BitmapShader(bitmap2, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);

// ComposeShader:结合两个 Shader
Shader shader = new ComposeShader(shader1, shader2, PorterDuff.Mode.SRC_OVER);  
paint.setShader(shader);

...

canvas.drawCircle(300, 300, 300, paint);  

注意:上面这段代码中我使用了两个 BitmapShader 来作为 ComposeShader() 的参数,而 ComposeShader() 在硬件加速下是不支持两个相同类型的 Shader 的,所以这里也需要关闭硬件加速才能看到效果
构造方法:ComposeShader(Shader shaderA, Shader shaderB, PorterDuff.Mode mode)

参数: shaderA, shaderB:两个相继使用的 Shader mode: 两个 Shader 的叠加模式,即 shaderA 和 shaderB 应该怎样共同绘制。它的类型是 PorterDuff.Mode 。

PorterDuff.Mode PorterDuff.Mode 是用来指定两个图像共同绘制时的颜色策略的。它是一个 enum,不同的 Mode 可以指定不同的策略。「颜色策略」的意思,就是说把源图像绘制到目标图像处时应该怎样确定二者结合后的颜色,而对于 ComposeShader(shaderA, shaderB, mode) 这个具体的方法,就是指应该怎样把 shaderB 绘制在 shaderA 上来得到一个结合后的 Shader。 没有听说过 PorterDuff.Mode 的人,看到这里很可能依然会一头雾水:「什么怎么结合?就……两个图像一叠加,结合呗?还能怎么结合?」你还别说,还真的是有很多种策略来结合。 最符合直觉的结合策略,就是我在上面这个例子中使用的 Mode: SRC_OVER。它的算法非常直观:就像上面图中的那样,把源图像直接铺在目标图像上。不过,除了这种,其实还有一些其他的结合方式。例如如果我把上面例子中的参数 mode 改为 PorterDuff.Mode.DST_OUT,就会变成挖空效果:

Android绘制:Shader_第11张图片
image.png

而如果再把 mode 改为 PorterDuff.Mode.DST_IN,就会变成蒙版抠图效果:

Android绘制:Shader_第12张图片
image.png

你可能感兴趣的:(Android绘制:Shader)