Paint 详解
Android 中的 Paint 我们可以理解为画画中的画笔,画笔往往有多种颜色和粗细。Paint 只有一个,但是他可以设置相关属性,来实现各种画笔的特性。我们作画时是用画笔在画板上作画,这里的 Paint 就是我们的画笔,画板就是 Android 中的 Cavans 了,这节我们直谈 Paint,Cavans 就不过多介绍。
常用 API
我们列举出了 Paint 常见的一些 API,其他相关 API 官网 Paint 都有相应介绍。
mPaint = new Paint();//初始化
mPaint.setColor(Color.RED);//设置颜色
mPaint.setARGB(255,255,255,0);//设置透颜色 0~255
mPaint.setAlpha(200);//设置透明度, 0~255
mPaint.setAntiAlias(true);//设置抗锯齿
mPaint.setStyle(Paint.Style.STROKE);//描边效果
mPaint.setStrokeWidth(4);//描边宽度
mPaint.setStrokeCap(Paint.Cap.ROUND);//描边圆角效果
mPaint.setStrokeJoin(Paint.Join.MITER);//描边拐角风格
mPaint.setShader(new SweepGradient(200,200,Color.BLUE,Color.RED));//设置渲染器
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DARKEN));//设置图层混合模式
mPaint.setColorFilter(new LightingColorFilter(0x00ffff,0x000000));//设置颜色过滤器
mPaint.setFilterBitmap(true);//设置双线性过滤
mPaint.setMaskFilter(new BlurMaskFilter(10,BlurMaskFilter.Blur.NORMAL));//设置画笔遮罩滤镜,传入度数和样式
mPaint.setTextScaleX(2);//设置文本缩放倍数
mPaint.setTextSize(38);//设置文本大小
mPaint.setTextAlign(Paint.Align.LEFT);//设置文本对齐方式
mPaint.setUnderlineText(true);//设置文本下划线
String str = "测试文本";
Rect rect = new Rect();
mPaint.getTextBounds(str,0,str.length(),rect);//测量文本大小,将文本大小信息存放在rect中
mPaint.measureText(str);//获取文本宽度
mPaint.getFontMetrics();//获取字体度量对象
部分 API 详解
这里我们挑一些不是很直观的说一下。
setStyle(Style style)
可以看到 setStyle 接受一个 Style 类型的参数,这是一个枚举类,对应的枚举值对应的解释。下面的效果图第一个为描边,第二个为充满,第三个为充满和描边。
/**
* The Style specifies if the primitive being drawn is filled,stroked, or
* both (in the same color). The default is FILL.
*
* Style指定绘制的图元是否被填充,描边或两者(以相同的颜色)。默认值为FILL。
*/
public enum Style {
//充满
FILL (0),
//描边
STROKE (1),
//充满和描边
FILL_AND_STROKE (2);
}
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
mPaint.setStrokeWidth(50);
mPaint.setStyle(Paint.Style.STROKE);
canvas.drawCircle(150,150,100,mPaint);
canvas.translate(0,250);
mPaint.setStyle(Paint.Style.FILL);
canvas.drawCircle(150,150,100,mPaint);
canvas.translate(0,250);
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
canvas.drawCircle(150,150,100,mPaint);
}
setStrokeCap(Cap cap)
设置画笔的头,这个 Cap 是一个枚举类,一共有三个值。给 Paint 分别设置响应值后,运行效果去下图
public enum Cap {
BUTT (0),
ROUND (1),
SQUARE (2);
}
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
mPaint.setStrokeWidth(50);
mPaint.setStrokeCap(Paint.Cap.BUTT);
canvas.drawLine(100,100,300,100,mPaint);
canvas.translate(0,100);
mPaint.setStrokeCap(Paint.Cap.ROUND);
canvas.drawLine(100,100,300,100,mPaint);
canvas.translate(0,100);
mPaint.setStrokeCap(Paint.Cap.SQUARE);
canvas.drawLine(100,100,300,100,mPaint);
canvas.translate(0,100);
}
setStrokeJoin(Join join)
设置画笔的拐角风格,Join 对应有三个值,效果如下。
setShader(Shader shader)
设置画笔渲染器 Shader 有5中默认实现,分别是
- LinearGradient 线性渲染器
- RadialGradient 环形渲染器
- SweepGradient 扫描渲染器
- BitmapShader 位图渲染器
- ComposeShader 组合渲染器,如LinearGradient + RadialGradient
下面我们来看看他们各自实现方式和实现结果。相关参数和注释已经标明,就不做过多解释了。
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
canvas.save();
canvas.translate(100,100);
/**
* 现行渲染器
* LinearGradient(float x0, float y0, float x1, float y1, @NonNull @ColorInt int colors[], @Nullable float positions[], @NonNull TileMode tile)
* (x0,y0),(x1,y1):渐变 起始点 和 结束点 的坐标
* color0,color1:渐变 开始点 和 结束点 的颜色,16进制表示,必须带有透明度
* colors:渐变数组
* positions:位置数组,positions 的取值范围【0,1】,作用是指定某个位置的颜色值,如果为 null,则默认线性渐变
* tile:指定控件区域 大于 指定的渐变区域时,空白区域的颜色填充方法
*/
Shader linearGradient = new LinearGradient(0,0,300,300,new int[]{Color.RED,Color.BLUE},new float[]{0.5f,1f},Shader.TileMode.CLAMP);
mPaint.setShader(linearGradient);
canvas.drawRect(0,0,300,300,mPaint);
canvas.translate(500,0);
/**
* 环形渲染器
* RadialGradient(float centerX, float centerY, float radius, @NonNull @ColorInt int colors[], @Nullable float stops[], @NonNull TileMode tileMode)
* RadialGradient(float centerX, float centerY, float radius, @ColorInt int centerColor, @ColorInt int edgeColor, @NonNull TileMode tileMode)
* centerX,centerY:shader中心坐标
* radius:渐变半径
* stoops:渐变位置数组,类似扫描渐变的 positions 数组,取值 [0,1],中心点为0,半径达到位置时为1
* tileMode:shader 没有覆盖的范围以外 的 填充模式
*/
Shader radialGradient = new RadialGradient(150,150,300,new int[]{Color.RED,Color.BLUE},null,Shader.TileMode.CLAMP);
mPaint.setShader(radialGradient);
canvas.drawCircle(150,150,150,mPaint);
canvas.restore();
canvas.save();
canvas.translate(100,500);
/**
* 扫描渲染器
* SweepGradient(float cx, float cy, @ColorInt int color0, @ColorInt int color1)
* SweepGradient(float cx, float cy, @NonNull @ColorInt int colors[], @Nullable float positions[])
* cx,cy:渐变中心的坐标
* color0,color1:渐变开始 和 渐变结束的颜色
* colors ,positions:类似 LinearGradient,用于多颜色渐变,当 positions 为 null 时,根据颜色线性渐变
*/
Shader sweepGradient = new SweepGradient(150,150,Color.RED,Color.BLUE);
mPaint.setShader(sweepGradient);
canvas.drawCircle(150,150,150,mPaint);
canvas.translate(400,0);
/**
* 位图渲染器
* BitmapShader(@NonNull Bitmap bitmap, @NonNull TileMode tileX, @NonNull TileMode tileY)
* Bitmap:渲染的位图
* tileX:x 轴方向的TileMode
* tileY:y 轴方向的TileMode
* public enum TileMode {
* //绘制区域超过渲染区域的部分,以最后一个像素拉伸充满
* CLAMP(0),
* //绘制区域超过渲染区域的部分,重复充满
* REPEAT(1),
* //绘制区域超过渲染区域的部分,镜像翻转充满
* MIRROR(2);
* }
*/
Shader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.MIRROR);
mPaint.setShader(bitmapShader);
canvas.drawRect(0,0,500,500,mPaint);
canvas.restore();
canvas.translate(100,1000);
/**
* 组合渲染器
* ComposeShader(@NonNull Shader shaderA, @NonNull Shader shaderB, @NonNull Xfermode mode)
* ComposeShader(@NonNull Shader shaderA, @NonNull Shader shaderB,@NonNull PorterDuff.Mode mode)
* shaderA,shaderB:要混合的两种 shader
* Xfermode mode:两种 shader 的组合模式
* PorterDuff.mode mode:两种 shader 颜色模式
*/
Shader bitmapShaderC = new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.MIRROR);
Shader linearGradientC = new LinearGradient(0,0,500,500,new int[]{Color.RED,Color.BLUE},new float[]{0f,1f},Shader.TileMode.CLAMP);
// Shader shader = new ComposeShader(bitmapShaderC,linearGradientC, PorterDuff.Mode.MULTIPLY);
Shader shader = new ComposeShader(bitmapShaderC,linearGradientC, PorterDuffXfermode.);
mPaint.setShader(shader);
canvas.drawRect(0,0,500,500,mPaint);
}
运行结果如下