0.什么是Shader?
Shader翻译成中文叫做着色器,通常我们使用Canvas的drawXXX方法是绘制图形,而画笔的Shader定义的就是图形的着色和外观。
下面就来介绍Android中的Shader。
1.BitmapShader
位图图像渲染,用BitMap对绘制的图形进行渲染着色,简单来说是用图片对图形进行贴图。使用场景有:圆形头像,放大镜效果。
BitmapShader在实例化时需要传入三个参数
public BitmapShader(@NonNull Bitmap bitmap, TileMode tileX, TileMode tileY)
第一个参数为需要渲染的Bitmap,第二个和第三个分别为X轴Y轴上的TileMode。
TileMode有三个枚举类型:
public enum TileMode {
/**
* replicate the edge color if the shader draws outside of its
* original bounds
*/
CLAMP (0),
/**
* repeat the shader's image horizontally and vertically
*/
REPEAT (1),
/**
* repeat the shader's image horizontally and vertically, alternating
* mirror images so that adjacent images always seam
*/
MIRROR (2);
...
}
- CLAMP 拉伸最后一个像素铺满
- MIRROR 横向纵向不足处不断翻转镜像平铺
- REPEAT 横向纵向不足的重复放置
看一下简单的小例子
- CLAMP
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(mBitmap, 0, 0, null);
canvas.translate(0, mHeight);
BitmapShader bitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
mPaint.setShader(bitmapShader);
mPaint.setAntiAlias(true);
//注意此处时绘制圆形,背景是通过着色器绘制的
canvas.drawOval(0, 0, mWidth, mHeight, mPaint);
}
不过这看不出来TileMode的作用,我们将绘制区域放大一些
canvas.drawRect(0, 0, 1000, 500, mPaint);
可以看出图片的区域被强制拉伸了
- MIRROR
现在把TileMode改成MIRROR再看效果
BitmapShader bitmapShader = new BitmapShader(mBitmap, Shader.TileMode.MIRROR, Shader.TileMode.MIRROR);
超出图片范围的区域变成了镜像
- REPEAT
超出范围的区域重复显示,这里不再演示
2.Gradient
2.1 LinearGradient
线性渲染,使用的场景有:霓虹灯文字,倒影图片
private void drawLinearGradient(Canvas canvas) {
int[] mColors = {Color.RED, Color.GREEN, Color.BLUE, Color.YELLOW};
LinearGradient linearGradient = new LinearGradient(0, 0, 800, 800, mColors, null, Shader.TileMode.CLAMP);
mPaint.setShader(linearGradient);
canvas.drawRect(0, 0, 800, 800, mPaint);
}
2.2 RadialGradient
private void drawRadialGradient(Canvas canvas) {
int[] mColors = {Color.RED, Color.GREEN, Color.BLUE, Color.YELLOW};
RadialGradient mRadialGradient = new RadialGradient(300, 300, 100, mColors, null, Shader.TileMode.REPEAT);
mPaint.setShader(mRadialGradient);
canvas.drawCircle(300, 300, 300, mPaint);
}