Paint.Shader(着色器)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010870167/article/details/81304257

Shader

通过Paint.setShader(Shader shader)来设置我们要显示图形的颜色.
通常我们并不直接使用Shader,而是使用它的子类来实现我们所需要实现的功能
它的子类:BitmapShader LinearGradient SweepGradient RadialGradient ComposeShader

TileMode

着色器平铺模式,一共有三种

  • TileMode.CLAMP : 拉伸
  • TileMode.REPEAT : 重复
  • TileMode.MIRROR : 镜像

BitmapShader(位图着色器)

  • 第一种情况:画图时边界小于等于位图的边界
String text = "Shader";
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.headimg);
BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.MIRROR, Shader.TileMode.MIRROR);//(1)
// BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.MIRROR, Shader.TileMode.MIRROR);//(2)
// BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);//(3)
Paint paint = new Paint();
paint.setShader(bitmapShader);
// canvas.drawRect(0, 0, bitmap.getWidth(), bitmap.getHeight(), paint);
canvas.drawBitmap(bitmap,0,0,paint);


代码效果图:当Rect的边界为图片的边界时,无论使用哪种平铺方式页面显示的效果相同,都是讲bitmap完整显示在屏幕上,所以我们可以得出,如果Rect的边界小于图片的边界时,屏幕上就只显示图片的一部分(按照Rect的边界显示)

同时我们还可以使用canvas画多种形状的图形,这时可以把bitmap当成画布的背景:圆形头像,五角星图形,多边形,带弧度的矩形等

这里写图片描述
* 第二种情况,画图时Rect的边界超出位图的边界

String text = "Shader";
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.headimg);
BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.MIRROR, Shader.TileMode.MIRROR);//(1)
// BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.MIRROR, Shader.TileMode.MIRROR);//(2)
// BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);//(3)
Paint paint = new Paint();
paint.setShader(bitmapShader);
// canvas.drawRect(0, 0, n*bitmap.getWidth(), n*bitmap.getHeight(), paint);

(1)在x,y方向 使用边缘拉伸模式会在图片在对应的x,y方向上将边缘的一个像素进行拉伸、扩展.(注意先在y方向上拉升,在拉升x方向)
这里写图片描述

(2) 在x,y方向使用镜像模式会将图片在对应的x,y方向上镜像翻转复制,
这里写图片描述

(3) 在x,y方向上使用重复模式会将图片在对应的x,y方向上进行复制.
这里写图片描述

LinearGradient(线性渐变)

这是一个线性渐变的处理类,含有两个构造函数:
1. public LinearGradient (float x0, float y0, float x1, float y1, int color0, int color1, Shader.TileMode tile)
(x0,y0)表示渐变的起点坐标,(x1,y1)则表示渐变的终点坐标,而color0和color1则表示起点的颜色和终点的颜色,TileMode表示平铺模式.

  1. public LinearGradient (float x0, float y0, float x1, float y1, int[] colors, float[] positions, Shader.TileMode tile)
    colors和positions都是数组,表示我们可以传入多个颜色和颜色的位置.

示例:
(1) 第一个构造函数:

Shader shader = new LinearGradient(0, 0, 400, 400, Color.RED, Color.YELLOW, Shader.TileMode.REPEAT);
paint.setShader(shader);
canvas.drawRect(0, 0, 600, 600, paint);

效果图:
这里写图片描述
绘制区域大于填充区域
(2) 第二个构造函数

Shader shader = new LinearGradient(0, 0, 200, 200,
        new int[] { Color.RED, Color.YELLOW, Color.GREEN, Color.CYAN, Color.BLUE },
        new float[] { 0, 0.1F, 0.5F, 0.7F, 0.8F } , Shader.TileMode.MIRROR);
paint.setShader(shader);
canvas.drawRect(0, 0, 400, 400, paint);

这里写图片描述
当我们吧position设置为null的时候效果如下:
这里写图片描述
线性渐变的用途
1. 绘制图片阴影
思路:
绘制倒影需要一张原图,然后我们拷贝一张进行矩阵翻转,吧他放在下面,作为倒影图.倒影图需要渐变消失,bitmap没有提供渐变消失效果,所以我们可以尝试混合模式.混合模式中,需要两张图片,一张是倒影图,一张是渐变图.倒影图的渐变是线性渐变,从无到有.
混合模式使用DST_IN.(使用的是xfermode混合模式)
PorterDuff.Mode.DST_IN
计算方式:[Sa * Da, Sa * Dc];
说明:只在源图像和目标图像相交的地方绘制目标图像

// 为了突出效果,先绘制一个灰色的画布
canvas.drawColor(Color.GRAY);
int x = 200, y = 200;
// 获取源图
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.headimg);
// 实例化一个矩阵对象
Matrix matrix = new Matrix();
matrix.setScale(1F, -1F);
// 产生和原图大小一样的倒影图
Bitmap refBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false);
// canvas.drawBitmap(refBitmap,x,y,paint);
// 绘制好原图
canvas.drawBitmap(bitmap, x, y, null);
// 保存图层。这里保存的图层宽度是原图绘制区域的宽度,高度是原图绘制区域两倍的高度,包含了绘制倒影的区域。
int sc = canvas.saveLayer(x, y + bitmap.getHeight(), x + bitmap.getWidth(), y + bitmap.getHeight() * 2, null, Canvas.ALL_SAVE_FLAG);
// 绘制倒影图片,绘制的区域紧贴原图的底部
canvas.drawBitmap(refBitmap, x, y + bitmap.getHeight(), null);
// 设置好混合模式
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
/*
 *  设置线性渐变模式。
 *  这里绘制的高度是原图的1/4,也就说倒影最终的区域也就是原图的1/4
 *  颜色是从Color.BLACK到透明,用于和倒影图做混合模式。
 *  模式是边缘拉伸模式,这里没用到
 */
paint.setShader(new LinearGradient(x, y + bitmap.getHeight(),
        x, y + bitmap.getHeight() + bitmap.getHeight() / 4,
        Color.BLACK, Color.TRANSPARENT, Shader.TileMode.CLAMP));
// 画一个矩形区域,作为目标图片,用来做混合模式
canvas.drawRect(x, y + bitmap.getHeight(), x + refBitmap.getWidth(), y + bitmap.getHeight() * 2, paint);
paint.setXfermode(null);
// 回复图层
canvas.restoreToCount(sc);

这里写图片描述
我们的倒影还有点问题,就是没有实现倾斜,倾斜实际上可以通过对图片进行(matrix变化)来实现

SweepGradient(扫描渐变)

梯度渐变,也称之为扫描式渐变,因为其效果有点类似雷达的扫描效果,他也有两个构造方法:
1. SweepGradient(float cx, float cy, int[] colors, float[] positions)
例如:

SweepGradient sweepGradient = new SweepGradient(200, 200, new int[]{Color.YELLOW,Color.RED, Color.WHITE, Color.GREEN}, null);
mPaint.setShader(sweepGradient);
canvas.drawRect(0, 0, 2160, 2500, mPaint);

效果图:
这里写图片描述

  1. SweepGradient(float cx, float cy, int color0, int color1)
    (cx,cy)是远行的坐标,颜色梯度从color0到color1的渐变.
    例如:
SweepGradient sweepGradient = new SweepGradient(200f,200f,Color.RED,Color.YELLOW);
mPaint.setShader(sweepGradient);
canvas.drawRect(0,0,2160,2500,mPaint);

效果图:
这里写图片描述
该类可以实现雷士雷达扫描效果,通过确定中心点和色值渐变,画出某一帕帧的图,让后通过旋转实现雷达扫描效果

RadialGradient(射线渐变)

径向渐变,径向渐变说的简单点就是个圆形中心向四周渐变的效果,他也一样有两个构造方法:
1. RadialGradient (float centerX, float centerY, float radius, int centerColor, int edgeColor, Shader.TileMode tileMode)
(centerX,centerY)是圆心的坐标,radius是半径,centerColor是边缘的颜色,edgeColor是外围的颜色,最后是模式。
示例:

Shader shader = new RadialGradient(200, 200, 200, Color.RED, Color.GREEN, Shader.TileMode.CLAMP);
mPaint.setShader(shader);
canvas.drawRect(0, 0, 400, 400, mPaint);

这里写图片描述
2. RadialGradient (float centerX, float centerY, float radius, int[] colors, float[] stops, Shader.TileMode tileMode)
这个就是添加了多个色彩,设置色彩的位置,其他同上.

Shader shader = new RadialGradient(200, 200, 200, new int[]{Color.WHITE,Color.YELLOW,Color.GREEN,Color.RED},new float[]{0.0f,0.4f,0.6f,0.8f} ,Shader.TileMode.CLAMP);
mPaint.setShader(shader);
canvas.drawRect(0, 0, 400, 400, mPaint);

效果图:
这里写图片描述

ComposeShader(混合着色器)

组合Shader的意思,顾名思义就是两个Shader组合在一起作为一个新Shader
他有两个构造函数:
ComposeShader (Shader shaderA, Shader shaderB, Xfermode mode)
ComposeShader (Shader shaderA, Shader shaderB, PorterDuff.Mode mode)
一个指定了只能用PorterDuff的混合模式而另一个是Xfermode下的混合模式

Matrix对Shader的效果

Paint mPaint = new Paint();
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.headimg);
BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
Matrix matrix = new Matrix();
matrix.setTranslate(180, 180);
// matrix.setTranslate(0, 0);
bitmapShader.setLocalMatrix(matrix);
mPaint.setShader(bitmapShader);
mPaint.setColor(Color.RED);
canvas.drawRect(0, 0, 800, 1600, mPaint);

上述代码的效果是:(1).根据矩阵改变图形位置,(2).将图形画到画布上,(3).根据TileMode格式对图形进行拉伸变化,拉伸的位置是从移动后的开始点向y,x轴的负方向进行拉伸效果,从移动后的右下角向x,y轴进行拉伸效果:

猜你喜欢

转载自blog.csdn.net/u010870167/article/details/81304257