大有可为的着色器:Shader
平时开发的时候或多或少都接触过相关的技术,但是却没有系统详细的学习一下。Android设计到的知识点很多,特点广泛而杂。有网络相关的,硬件相关的,图形图像相关的等等,每一点都得或多或少需要学习掌握一些。
1、Shader
Shader直译过来就叫“着色器”,该类是抽象的基础类,Shader共有五个子类:BitmapShader、LinearGradient、RadialGradient、SweepGradient、ComposeShader,分别代表不同类型的着色器,具体功能后面再仔细看。
1.1、关联Paint
用来设置给Paint画笔,使用Shader setShader(Shader shader)方法。
mPaint.setShader(shader);给Paint设置好着色器之后,使用该画笔绘制的对象都将从着色器获取颜色。
1.2、填充模式
着色器也是有范围的,设置了一定的区域范围,Paint从这些范围内可以拿到颜色,但是Paint绘制的图像可能比这大,那么就需要一个策略:如何确定着色器“管辖”区域外的颜色呢?
就有了如下三种填充模式:TileMode.CLAMP、TileMode.REPEAT、TileMode.MIRROR。
public enum TileMode {
/**
* 如果着色器超出其原始边界,则复制边缘颜色
*/
CLAMP (0),
/**
* 水平和垂直重复着色器的图像
*/
REPEAT (1),
/**
* 水平和垂直重复着色器的图像,交替生成镜像,以便相邻的图像始终缝合
*/
MIRROR (2);
}2、BitmapShader
BitmapShader类似于Photoshop中的印章工具,Paint绘制的区域使用Bitmap中的图像来着色。
2.1、构造BitmapShader
BitmapShader的构造函数如下,需要指定Bitmap图像,以及X、Y轴的填充模式。
/**
* Call this to create a new shader that will draw with a bitmap.
*
* @param bitmap The bitmap to use inside the shader
* @param tileX The tiling mode for x to draw the bitmap in.
* @param tileY The tiling mode for y to draw the bitmap in.
*/
public BitmapShader(Bitmap bitmap,TileMode tileX,TileMode tileY) {
this(bitmap, tileX.nativeInt, tileY.nativeInt);
}2.2、示例
构造好BitmapShader,并设置给Paint画笔,绘制一个矩形区域。看看不同的填充模式,效果如何?
①TileMode.CLAMP:使用着色器边缘填充其它区域

②TileMode.REPEAT:绘制的区域, 超过了着色器颜色范围,那么就用重复策略

③TileMode.MIRROR:不断的通过镜像填充

3、LinearGradient
LinearGradient线性渐变着色器,实现颜色的线性渐变效果。在自定义Drawable背景的时候有接触过,使用<gradient/>标签添加渐变效果,详见ShapeDrawable:Android自定义背景。
3.1、构造线性着色器
有如下5中线性着色器构造方法。前四个参数是指定区域,指定开始颜色和结束时的颜色,最后一个参数TileMode是填充模式。关于Color颜色,详见《Color详解》。
LinearGradient(float x0, float y0, float x1, float y1,int color0,int color1,TileMode tile)
LinearGradient(float x0, float y0, float x1, float y1,long color0,long color1,TileMode tile)线性变换中可以指定多个颜色值[],已经对应的位置[]。
LinearGradient(float x0, float y0, float x1, float y1,int[] colors,float[] positions,TileMode tile)
LinearGradient(float x0, float y0, float x1, float y1,long[] colors,float[] positions,TileMode tile)
LinearGradient(float x0, float y0, float x1, float y1,long[] colors,float[] positions,TileMode tile,ColorSpace colorSpace)3.2、示例
构造一个线性颜色着色器设置给Paint画笔,再使用该画笔绘制文字及其它图形。
mPaint.setShader(new LinearGradient(0, 0,200, 200, 0xff225a1f, 0xffd71345, Shader.TileMode.MIRROR));
canvas.drawText(text, 0, 200, mPaint);
再结合动画ValueAnimator就可以实现文字的色彩变换。关于属性动画详见《属性动画:ValueAnimator及其监听器》。
//获取要绘制文字的长度
length = mPaint.measureText(text);
//创建属性动画
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, length * 2);
valueAnimator.setDuration(3000);
valueAnimator.setRepeatMode(ValueAnimator.RESTART);
valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
start = (float) animation.getAnimatedValue();
postInvalidate();
}
});
valueAnimator.start();
4、RadialGradient
RadialGradient放射渐变着色器
4.1、构造放射渐变着色器
有如下5中构造方法,就不在一一详细介绍。需要指定中心坐标以及渐变半径radius。
RadialGradient(float centerX, float centerY, float radius,int[] colors,float[] stops,TileMode tileMode)
RadialGradient(float centerX, float centerY, float radius,long[] colors,float[] stops,TileMode tileMode)
RadialGradient(float centerX, float centerY, float radius,long[] colors,float[] stops,TileMode tileMode, ColorSpace colorSpace)
RadialGradient(float centerX, float centerY, float radius,int centerColor,int edgeColor,TileMode tileMode)
RadialGradient(float centerX, float centerY, float radius,long centerColor,long edgeColor,TileMode tileMode)4.2、示例
使用该着色器结合动画可以实现各种效果。
//给画笔设置着色器
mPaint.setShader(new RadialGradient(600, 600, radial + 1, 0xff225a1f, 0xffd71345, Shader.TileMode.CLAMP));
//使用该画笔绘制圆形,结合动画会呈现各种效果
canvas.drawCircle(600, 600, 200, mPaint);
5、SweepGradient
SweepGradient扫描渐变着色器。
5.1、构造扫描渐变着色器
如下几种构造函数。注意只有一个坐标点,意味着只需要指定中心区域,扫描范围是无限的。
SweepGradient(float cx, float cy,int[] colors,float[] positions)
SweepGradient(float cx, float cy,long[] colors,float[] positions)
SweepGradient(float cx, float cy,long[] colors,float[] positions, ColorSpace colorSpace)
SweepGradient(float cx, float cy,int color0,int color1)
SweepGradient(float cx, float cy,long color0,long color1)5.2、示例
简单的渐变图如下,如何实现雷达扫描图的动画效果呢?可以发挥想象力。
mPaint.setShader(new SweepGradient(600, 600, 0xff225a1f, 0xffd71345));
canvas.drawCircle(600, 600, 200, mPaint);

6、ComposeShader
ComposeShader组合着色器,将其它着色器组合成为一个混合着色器。
6.1、组合着色器
有两种构造方法
ComposeShader(Shader shaderA,Shader shaderB,PorterDuff.Mode mode)
ComposeShader(Shader shaderA,Shader shaderB,BlendMode blendMode)6.2、混合模式*
组合两个不同的着色器有如下两种模式:PorterDuff.Mode和BlendMode 。简单了解一下即可,也不需要记住,会用比会背更重要!
①PorterDuff.Mode
public enum Mode {
// these value must match their native equivalents. See SkXfermode.h
CLEAR (0),
SRC (1),
DST (2),
SRC_OVER (3),
DST_OVER (4),
SRC_IN (5),
DST_IN (6),
SRC_OUT (7),
DST_OUT (8),
SRC_ATOP (9),
DST_ATOP (10),
XOR (11),
DARKEN (16),
LIGHTEN (17),
MULTIPLY (13),
SCREEN (14),
ADD (12),
OVERLAY (15);
}②BlendMode
public enum BlendMode {
CLEAR(0),
SRC(1),
DST(2),
SRC_OVER(3),
DST_OVER(4),
SRC_IN(5),
DST_IN(6),
SRC_OUT(7),
DST_OUT(8),
SRC_ATOP(9),
DST_ATOP(10),
XOR(11),
PLUS(12),
MODULATE(13),
SCREEN(14),
OVERLAY(15),
DARKEN(16),
LIGHTEN(17),
COLOR_DODGE(18),
COLOR_BURN(19),
HARD_LIGHT(20),
SOFT_LIGHT(21),
DIFFERENCE(22),
EXCLUSION(23),
MULTIPLY(24),
HUE(25),
SATURATION(26),
COLOR(27),
LUMINOSITY(28);
}相关资料:
Reference > Shader">Android Developers > Reference > Shader
Reference > BitmapShader">Android Developers > Reference > BitmapShader
Reference > LinearGradient">Android Developers > Reference > LinearGradient
Reference > RadialGradient">Android Developers > Reference > RadialGradient
Reference > SweepGradient">Android Developers > Reference > SweepGradient
Reference > ComposeShader">Android Developers > Reference > ComposeShader

