概述
我们在用Android中的Canvas绘制各种图形时,可以通过Paint.setShader(shader)
方法为画笔Paint设置shader,这样就可以绘制出多彩的图形。那么Shader是什么呢?做过GPU绘图的同学应该都知道这个词汇,Shader就是着色器的意思。我们可以这样理解,Canvas中的各种drawXXX方法定义了图形的形状,画笔中的Shader则定义了图形的着色、外观,二者结合到一起就决定了最终Canvas绘制的被色彩填充的图形的样子。
类android.graphics.Shader
有五个子类,分别是:BitmapShader、LinearGradient、RadialGradient、SweepGradient和ComposeShader,下面依次对这几个类的使用分别说明。
BitmapShader
BitmapShader,顾名思义,就是用Bitmap对绘制的图形进行渲染着色,其实就是用图片对图形进行贴图。
BitmapShader构造函数如下所示:
1 |
BitmapShader(Bitmap bitmap, Shader.TileMode tileX, Shader.TileMode tileY) |
第一个参数是Bitmap对象,该Bitmap决定了用什么图片对绘制的图形进行贴图。
第二个参数和第三个参数都是Shader.TileMode类型的枚举值,有以下三个取值:CLAMP 、REPEAT 和 MIRROR。
- CLAMP
CLAMP表示,当所画图形的尺寸大于Bitmap的尺寸的时候,会用Bitmap四边的颜色填充剩余空间。我们有一个Bitmap,如下所示:
注意,我们这张图片的四个角是有一定的圆弧的,也就是该Bitmap的四个角点处的像素都是透明的。
我们使用该Bitmap,演示TileMode为CLAMP的效果,代码如下所示:
1 2 3 |
BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); paint.setShader(bitmapShader); canvas.drawRect(0, 0, bitmap.getWidth() * 2, bitmap.getHeight() * 2, paint); |
效果如下所示:
我们可以看到,由于我们所绘制的矩形矩形区域比Bitmap大,Bitmap就用右侧边和下侧边的最外层的颜色填充了矩形区域。由于原Bitmap右下角的像素是透明的,所以绘制的矩形的右下角就用透明填充了。
如果我们绘制的图形尺寸小于Bitmap尺寸,那么效果看起来就像是对原Bitmap裁剪了一下而已,如下所示:
我们可以看到,当我们所绘制的圆形尺寸小于Bitmap尺寸的时候,看起来的效果就是我们用所绘制的圆形对Bitmap进行了裁剪。
- REPEAT
REPEAT表示,当我们绘制的图形尺寸大于Bitmap尺寸时,会用Bitmap重复平铺整个绘制的区域。
示例代码如下所示:
1 2 3 |
BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT); paint.setShader(bitmapShader); canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), paint); |
效果如下所示:
- MIRROR
与REPEAT类似,当绘制的图形尺寸大于Bitmap尺寸时,MIRROR也会用Bitmap重复平铺整个绘图区域,与REPEAT不同的是,两个相邻的Bitmap互为镜像。
代码如下所示:
1 2 3 |
BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.MIRROR, Shader.TileMode.MIRROR); paint.setShader(bitmapShader); canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), paint); |
效果如下所示:
最后需要说的是,在构造BitmapShader时,tileX和tileY可以取不同的值,二者不用非得一致。
LinearGradient
我们可以用LinearGradient创建线性渐变效果,其有两个构造函数:
1 2 3 |
LinearGradient(float x0, float y0, float x1, float y1, int color0, int color1, Shader.TileMode tile) LinearGradient(float x0, float y0, float x1, float y1, int[] colors, float[] positions, Shader.TileMode tile) |
我们重点说一下第一个构造函数,在此基础上理解第二个构造函数就很简单了。
LinearGradient是用来创建线性渐变效果的,它是沿着某条直线的方向渐变的,坐标(x0,y0)就是这条渐变直线的起点,坐标(x1,y1)就是这条渐变直线的终点。需要说明的是,坐标(x0,y0)和坐标(x1,y1)都是Canvas绘图坐标系中的坐标。color0和color1分别表示了渐变的起始颜色和终止颜色。与BitmapShader类似,LinearGradient也支持TileMode,有以下三个取值:CLAMP 、REPEAT 和 MIRROR。
使用代码如下所示:
1 2 3 |
LinearGradient linearGradient = new LinearGradient(100, 100, 500, 500, Color.GREEN, Color.BLUE, Shader.TileMode.CLAMP); paint.setShader(linearGradient); canvas.drawRect(100, 100, 500, 500, paint); |
效果如下所示:
上面我们使用了CLAMP,但是由于我们绘制的矩形与渐变位置的大小一样大,所以CLAMP效果不明显。
我们把绘制的区域变大,还是用CLAMP,这次绘制整个Canvas大小的矩形。
类android.graphics.Shader
有五个子类,分别是:BitmapShader、LinearGradient、RadialGradient、SweepGradient和ComposeShader,下面依次对这几个类的使用分别说明。
BitmapShader
BitmapShader,顾名思义,就是用Bitmap对绘制的图形进行渲染着色,其实就是用图片对图形进行贴图。
BitmapShader构造函数如下所示:
1 |
BitmapShader(Bitmap bitmap, Shader.TileMode tileX, Shader.TileMode tileY) |
第一个参数是Bitmap对象,该Bitmap决定了用什么图片对绘制的图形进行贴图。
第二个参数和第三个参数都是Shader.TileMode类型的枚举值,有以下三个取值:CLAMP 、REPEAT 和 MIRROR。
- CLAMP
CLAMP表示,当所画图形的尺寸大于Bitmap的尺寸的时候,会用Bitmap四边的颜色填充剩余空间。我们有一个Bitmap,如下所示:
注意,我们这张图片的四个角是有一定的圆弧的,也就是该Bitmap的四个角点处的像素都是透明的。
我们使用该Bitmap,演示TileMode为CLAMP的效果,代码如下所示:
1 2 3 |
BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); paint.setShader(bitmapShader); canvas.drawRect(0, 0, bitmap.getWidth() * 2, bitmap.getHeight() * 2, paint); |
效果如下所示:
我们可以看到,由于我们所绘制的矩形矩形区域比Bitmap大,Bitmap就用右侧边和下侧边的最外层的颜色填充了矩形区域。由于原Bitmap右下角的像素是透明的,所以绘制的矩形的右下角就用透明填充了。
如果我们绘制的图形尺寸小于Bitmap尺寸,那么效果看起来就像是对原Bitmap裁剪了一下而已,如下所示:
我们可以看到,当我们所绘制的圆形尺寸小于Bitmap尺寸的时候,看起来的效果就是我们用所绘制的圆形对Bitmap进行了裁剪。
- REPEAT
REPEAT表示,当我们绘制的图形尺寸大于Bitmap尺寸时,会用Bitmap重复平铺整个绘制的区域。
示例代码如下所示:
1 2 3 |
BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT); paint.setShader(bitmapShader); canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), paint); |
效果如下所示:
- MIRROR
与REPEAT类似,当绘制的图形尺寸大于Bitmap尺寸时,MIRROR也会用Bitmap重复平铺整个绘图区域,与REPEAT不同的是,两个相邻的Bitmap互为镜像。
代码如下所示:
1 2 3 |
BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.MIRROR, Shader.TileMode.MIRROR); paint.setShader(bitmapShader); canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), paint); |
效果如下所示:
最后需要说的是,在构造BitmapShader时,tileX和tileY可以取不同的值,二者不用非得一致。
LinearGradient
我们可以用LinearGradient创建线性渐变效果,其有两个构造函数:
1 2 3 |
LinearGradient(float x0, float y0, float x1, float y1, int color0, int color1, Shader.TileMode tile) LinearGradient(float x0, float y0, float x1, float y1, int[] colors, float[] positions, Shader.TileMode tile) |
我们重点说一下第一个构造函数,在此基础上理解第二个构造函数就很简单了。
LinearGradient是用来创建线性渐变效果的,它是沿着某条直线的方向渐变的,坐标(x0,y0)就是这条渐变直线的起点,坐标(x1,y1)就是这条渐变直线的终点。需要说明的是,坐标(x0,y0)和坐标(x1,y1)都是Canvas绘图坐标系中的坐标。color0和color1分别表示了渐变的起始颜色和终止颜色。与BitmapShader类似,LinearGradient也支持TileMode,有以下三个取值:CLAMP 、REPEAT 和 MIRROR。
使用代码如下所示:
1 2 3 |
LinearGradient linearGradient = new LinearGradient(100, 100, 500, 500, Color.GREEN, Color.BLUE, Shader.TileMode.CLAMP); paint.setShader(linearGradient); canvas.drawRect(100, 100, 500, 500, paint); |
效果如下所示:
上面我们使用了CLAMP,但是由于我们绘制的矩形与渐变位置的大小一样大,所以CLAMP效果不明显。
我们把绘制的区域变大,还是用CLAMP,这次绘制整个Canvas大小的矩形。