1、Paint类
自定义控件具有很强的灵活性,可以根据你的想法画出各种各样的图案,在Android中如果是自定义控件的话,Paint这个类用的还是较多的,先来看一下这个类的注释:
/**
* The Paint class holds the style and color information about how to draw
* geometries, text and bitmaps.
*/
使用保存的样式和颜色信息,绘制几何图形,文本和bitmap。
2、Paint方法
mPaint.setColor(Color.RED);// 设置颜色
mPaint.setARGB(255, 255, 255, 0); // 设置 Paint对象颜色,范围为0~255
mPaint.setAlpha(200); // 设置alpha不透明度,范围为0~255
mPaint.setAntiAlias(true); // 抗锯齿
mPaint.setStyle(Paint.Style.FILL); //描边效果
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)); //设置颜色过滤器
3、线条形状
3.1 Paint. setAntiAlias
设置抗锯齿
3.2 Paint.Style
paint.setStyle(Paint.Style.FILL); //填充所有
paint.setStyle(Paint.Style.STROKE); //描边效果,只画出线条
paint.setStyle(Paint.Style.FILL_AND_STROKE); //填充内部和描边
3.3 Paint.cap
paint.setStrokeCap(Paint.Cap.BUTT); //默认效果,如绘制的正方形,就是正方行
paint.setStrokeCap(Paint.Cap.ROUND); //绘制的图形两边会有圆角效果,两边的圆角是在SQUARE 的基础上延申出一部分形成圆角
paint.setStrokeCap(Paint.Cap.SQUARE); //BUTT 的基础上,两边延申出去一部分
3.4 Paint.Join
paint.setStrokeJoin(Paint.Join.MITER);//拐角风格,直角
paint.setStrokeJoin(Paint.Join.BEVEL);//拐角风格,切割
paint.setStrokeJoin(Paint.Join.ROUND);//拐角风格,圆角
3.5 Paint. StrokeMiter
paint.setStrokeMiter(1.7f);
对于 setStrokeJoin() 的一个补充,它用于设置 MITER 型拐角的延长线的最大值。
4、drawBitmap
4.1 Paint.setXfermode
4.2 Paint.setDither
设置图像的抖动
paint.setDither(true);
4.3 Paint.setFilterBitmap
是否使用双线性过滤来绘制 Bitmap
图像在放大绘制的时候,默认使用的是最近邻插值过滤,这种算法简单,但会出现马赛克现象;而如果开启了双线性过滤,就可以让结果图像显得更加平滑。
paint.setFilterBitmap(true);
5、drawText
5.1 Paint.Align
paint.setTextAlign(Paint.Align.LEFT); //左对齐,默认
paint.setTextAlign(Paint.Align.CENTER);//居中对齐
paint.setTextAlign(Paint.Align.RIGHT); //右对齐
5.2 Paint.FontMetrics
字体的度量,是指对于指定字号的某种字体,在度量方面的各种属性,其描述参数包括:
Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
float top = fontMetrics.top;
float ascent = fontMetrics.ascent;
float descent = fontMetrics.descent;
float bottom = fontMetrics.bottom;
float leading = fontMetrics.leading;
baseline:字符基线
ascent:字符最高点到baseline的推荐距离
top:字符最高点到baseline的最大距离
descent:字符最低点到baseline的推荐距离
bottom:字符最低点到baseline的最大距离
leading:行间距,即前一行的descent与下一行的ascent之间的距离
参考:https://blog.csdn.net/flyeek/article/details/43934945
5.3 Paint.Measure
float[] measuredWidth = new float[16];
Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
//字符的高度
float textHeight = fontMetrics.descent + Math.abs(fontMetrics.ascent);
//字符串的长度;
float textLength = mPaint.measureText(text);
//measuredWidth每一个字符的长度;textWidths字符数
int textWidths = mPaint.getTextWidths(text, measuredWidth);
//截取的最大距离中字符个数
int breakText = mPaint.breakText(text, true, 50, null);
breakText()这个方法:
/**
* 计算出要截取的字符个数
*
* @param text 测量的字符串
* @param start 测量开始的位置
* @param end 测量结束的位置
* @param measureForwards 测量方向,true从前往后,false从后往前
* @param maxWidth 截取的字符串最大宽度
* @param measuredWidth 截取字符串实际宽度
* @return 需要截取的字符个数
*/
public int breakText(CharSequence text, int start, int end,
boolean measureForwards, float maxWidth,
float[] measuredWidth);
5.4 Paint.setShadowLayer
mPaint.setShadowLayer(10, 10, 10, Color.RED);
canvas.drawText("ANDROID", 0, 100, mPaint);
注意:
在硬件加速开启的情况下, setShadowLayer() 只支持文字的绘制,文字之外的绘制必须关闭硬件加速才能正常绘制阴影。
如果 shadowColor 是半透明的,阴影的透明度就使用 shadowColor 自己的透明度;而如果 shadowColor 是不透明的,阴影的透明度就使用 paint 的透明度。
6、PathEffect
使用 PathEffect 来给图形的轮廓设置效果。
Android 中的 6 种 PathEffect:
单一效果: CornerPathEffect、DiscretePathEffect、DashPathEffect、PathDashPathEffect
组合效果:SumPathEffect ComposePathEffect
6.1 CornerPathEffect
把所有拐角变成圆角
PathEffect effect = new CornerPathEffect(60);
mPaint.setPathEffect(effect);
canvas.drawPath(mPath, mPaint);
6.2 DiscretePathEffect
把线条进行随机的偏离,让轮廓变得乱七八糟。
DiscretePathEffect 具体的做法是,把绘制改为使用定长的线段来拼接,并且在拼接的时候对路径进行随机偏离。DiscretePathEffect(float segmentLength, float deviation) 的两个参数中, segmentLength 是用来拼接的每个线段的长度, deviation 是偏离量。这两个值设置得不一样,显示效果也会不一样。
PathEffect effect = new DiscretePathEffect(20, 10);
mPaint.setPathEffect(effect);
canvas.drawPath(mPath, mPaint);
6.3 DashPathEffect
使用虚线来绘制线条。
它的构造方法 DashPathEffect(float[] intervals, float phase) 中, 第一个参数 intervals 是一个数组,它指定了虚线的格式:数组中元素必须为偶数(最少是 2 个),按照「画线长度、空白长度、画线长度、空白长度」……的顺序排列,例如上面代码中的 20, 5, 10, 5 就表示虚线是按照「画 20 像素、空 5 像素、画 10 像素、空 5 像素」的模式来绘制;第二个参数 phase 是虚线的偏移量。
PathEffect effect = new DashPathEffect(new float[]{30,15,60, 15}, 10);
mPaint.setPathEffect(effect);
canvas.drawPath(mPath, mPaint);
6.4 PathDashPathEffect
这个方法比 DashPathEffect 多一个前缀 Path ,所以顾名思义,它是使用一个Path 来绘制「虚线」。
它的构造方法:PathDashPathEffect(Path shape, float advance, float phase, Style style );
PathDashPathE中, shape 参数是用来绘制的 Path ; advance 是两个相邻的 shape 段之间的间隔,不过注意,这个间隔是两个 shape 段的起点的间隔,而不是前一个的终点和后一个的起点的距离; phase 和 DashPathEffect 中一样,是虚线的偏移;最后一个参数 style,是用来指定拐弯改变的时候 shape 的转换方式。style 的类型为 PathDashPathEffect.Style ,是一个 enum ,具体有三个值:
TRANSLATE:位移
ROTATE:旋转
MORPH:变体
Path shape = new Path();
shape.moveTo(0,20);
shape.lineTo(20,0);
shape.lineTo(40, 20);
PathEffect effect = new PathDashPathEffect(shape,50,40, PathDashPathEffect.Style.TRANSLATE);
mPaint.setPathEffect(effect);
canvas.drawRoundRect(0,0, 400,300, 72,72, mPaint);
6.5 SumPathEffect
这是一个组合效果类的 PathEffect 。它的行为特别简单,就是分别按照两种PathEffect 分别对目标进行绘制。
PathEffect dashPathEffect = new DashPathEffect(new float[]{10, 10}, 10);
PathEffect discretePathEffect = new DiscretePathEffect(40, 20);
PathEffect sumPathEffect = new SumPathEffect(dashPathEffect, discretePathEffect);
mPaint.setPathEffect(sumPathEffect);
canvas.drawPath(mPath, mPaint);
6.6 ComposePathEffect
这也是一个组合效果类的 PathEffect 。不过它是先对目标 Path 使用一个PathEffect,然后再对这个改变后的 Path 使用另一个 PathEffect。
PathEffect dashPathEffect = new DashPathEffect(new float[]{10, 10}, 10);
PathEffect discretePathEffect = new DiscretePathEffect(40, 20);
PathEffect sumPathEffect = new ComposePathEffect(dashPathEffect, discretePathEffect);
mPaint.setPathEffect(sumPathEffect);
canvas.drawPath(mPath, mPaint);
它的构造方法ComposePathEffect(PathEffect outerpe, PathEffect innerpe) 中的两个PathEffect 参数, innerpe 是先应用的, outerpe 是后应用的。所以上面的代码就是「先偏离,再变虚线」。而如果把两个参数调换,就成了「先变虚线,再偏离」。
7、MaskFilter
为之后的绘制设置 MaskFilter。上一个方法 setShadowLayer() 是设置的在绘制层下方的附加效果;而这个 MaskFilter 和它相反,设置的是在绘制层上方的附加效果。
MaskFilter 有两种: BlurMaskFilter 和 EmbossMaskFilter。
7.1 BlurMaskFilter
模糊效果
MaskFilter filter = new BlurMaskFilter(50, BlurMaskFilter.Blur.INNER);
mPaint.setMaskFilter(filter);
canvas.drawBitmap(bitmap, 100, 100, mPaint);
它的构造方法 BlurMaskFilter(float radius, BlurMaskFilter.Blur style)中, radius 参数是模糊的范围, style 是模糊的类型。一共有四种:
NORMAL : 内外都模糊绘制
SOLID : 内部正常绘制,外部模糊
INNER : 内部模糊,外部不绘制
OUTER : 内部不绘制,外部模糊
7.2 EmbossMaskFilter
浮雕效果
EmbossMaskFilter (float[] direction, // 3个浮点值的数组,X、Y、Z方向指定光源
float ambient, // 环境光亮度,取值范围是0~1
float specular, // 反射等级,值如:8
float blurRadius) // 照明前的模糊量,值如:3
MaskFilter filter = new EmbossMaskFilter(new float[]{-1, 1, -1}, 1f, 8, 3.5f);
mPaint.setMaskFilter(filter);
canvas.drawText("ANDROID", 0, 200, mPaint);
效果不是很明显…
8.Shader
Shader 这个英文单词很多人没有见过,它的中文叫做「着色器」,也是用于设置绘制颜色的。在 Android 的绘制里使用 Shader ,并不直接用 Shader 这个类,而是用它的几个子类:
LinearGradient、RadialGradient、SweepGradient、BitmapShader、 ComposeShader
8.1 LinearGradient线性渲染
**
* 1.线性渲染,LinearGradient(float x0, float y0, float x1, float y1, @NonNull @ColorInt int colors[], @Nullable float positions[], @NonNull TileMode tile)
* (x0,y0):渐变起始点座标
* (x1,y1):渐变结束点座标
* colors:渐变数组
* positions:位置数组,position的取值范围[0,1],作用是指定某个位置的颜色值,如果传null,渐变就线性变化。
* tile:用于指定控件区域大于指定的渐变区域时,空白区域的颜色填充方法,分为三种:CLAMP(最后1像素拉伸) REPEAT(重复) MIRROR(镜影)
*/
//渲染一个x和y的座标点是(200, 100),颜色是从绿色到红色渐变,在0.6f(60%)的时候开始渐变成红色,1 最后是蓝色 ,绘制区域大于渲染器指定区域的填充是1像素拉伸
Shader lineShader = new LinearGradient(0, 0, 200, 0,
new int[]{Color.RED, Color.GREEN, Color.BLUE},
new float[]{0, 0.6f, 1},
Shader.TileMode.REPEAT);
8.2 RadialGradient环形渲染
/**
* 环形渲染,RadialGradient(float centerX, float centerY, float radius, @ColorInt int colors[], @Nullable float stops[], TileMode tileMode)
* centerX ,centerY:shader的中心座标,开始渐变的座标
* radius:渐变的半径
* centerColor,edgeColor:中心点渐变颜色,边界的渐变颜色
* colors:渐变颜色数组
* stoops:渐变位置数组,类似扫描渐变的positions数组,取值[0,1],中心点为0,半径到达位置为1.0f
* tileMode:shader未覆盖以外的填充模式。
*/
Shader shader = new RadialGradient(200, 200, 130,
new int[]{Color.GREEN, Color.YELLOW, Color.RED},
null, Shader.TileMode.REPEAT);
mPaint.setShader(shader);
8.3 SweepGradient扫描渲染
/**
* 扫描渲染,顺时针方向逐渐渐变渲染 SweepGradient(float cx, float cy, @ColorInt int color0,int color1)
* cx,cy 渐变中心座标
* color0,color1:渐变开始结束颜色
* colors,positions:类似LinearGradient,用于多颜色渐变,positions为null时,根据颜色线性渐变
*/
Shader shader = new SweepGradient(200, 200,
new int[]{Color.RED, Color.GREEN, Color.BLUE},
new float[]{0.5f, 0.3f,1});
8.4 BitmapShader位图渲染
/**
* 位图渲染,BitmapShader(@NonNull Bitmap bitmap, @NonNull TileMode tileX, @NonNull TileMode tileY)
* Bitmap:构造shader使用的bitmap
* tileX:X轴方向的TileMode
* tileY:Y轴方向的TileMode
REPEAT, 绘制区域超过渲染区域的部分,重复排版
CLAMP, 绘制区域超过渲染区域的部分,会以最后一个像素拉伸排版
MIRROR, 绘制区域超过渲染区域的部分,镜像翻转排版
*/
Shader shader = new BitmapShader(mBitmap, Shader.TileMode.MIRROR, Shader.TileMode.MIRROR);
8.5 ComposeShader组合渲染
Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.flower);
Shader bitmapShader = new BitmapShader(mBitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
LinearGradient linearGradient = new LinearGradient(0, 0, 200, 200,
new int[]{Color.RED, Color.GREEN, Color.BLUE},
null,
Shader.TileMode.REPEAT);
Shader shader = new ComposeShader(bitmapShader, linearGradient, PorterDuff.Mode.MULTIPLY);
mPaint.setShader(shader);
9、ColorFilter
ColorFilter 这个类,它的名字已经足够解释它的作用:为绘制设置颜色过滤。颜色过滤的意思,就是为绘制的内容设置一个统一的过滤策略,然后Canvas.drawXXX() 方法会对每个像素都进行过滤后再绘制出来。
ColorFilter 并不直接使用,而是使用它的子类。它共有三个子类:LightingColorFilter、PorterDuffColorFilter 和 ColorMatrixColorFilter。
9.1 LightingColorFilter 光照效果
/**
* 用来模拟简单的光照效果 LightingColorFilter(@ColorInt int mul, @ColorInt int add)
* mul:和目标像素相乘,默认0xffffff
* add:和目标像素相加,默认0x000000
* R' = R * mul.R / 0xff + add.R
* G' = G * mul.G / 0xff + add.G
* B' = B * mul.B / 0xff + add.B
*/
ColorFilter filter = new LightingColorFilter(0x00ffff, 0x000000);
如果你想去掉原像素中的红色,可以把它的 mul 改为 0x00ffff。绿色加强,可以把它的 add 改为 0x003000。
9.2 PorterDuffColorFilter 混合滤镜
/**
* 使用一个指定的颜色和一种指定的 PorterDuff.Mode 来与绘制对象进行合成
* PorterDuffColorFilter(@ColorInt int color, @NonNull PorterDuff.Mode mode)
* color: 指定的颜色
* mode:指定的 Mode
*/
ColorFilter filter = new PorterDuffColorFilter(Color.RED, PorterDuff.Mode.MULTIPLY);
9.3 ColorMatrixColorFilter
/**
* 使用一个 ColorMatrix 来对颜色进行处理。 ColorMatrix 这个类,内部是一个 4x5 的矩阵:
* [ a, b, c, d, e,
* f, g, h, i, j,
* k, l, m, n, o,
* p, q, r, s, t ]
* 对于颜色 [R, G, B, A] ,转换算法是这样的:
* R’ = a*R + b*G + c*B + d*A + e;
* G’ = f*R + g*G + h*B + i*A + j;
* B’ = k*R + l*G + m*B + n*A + o;
* A’ = p*R + q*G + r*B + s*A + t;
*/
ColorMatrix colorMatrix = new ColorMatrix();
colorMatrix.setSaturation(0.5f);
//colorMatrix.setRotate(0, 90);
//colorMatrix.setScale(0.5f,0.5f,0.5f,0.5f);
ColorFilter filter = new ColorMatrixColorFilter(colorMatrix)
ColorMatrix 有一些自带的方法可以做简单的转换,setSaturation(float sat) 来设置饱和度。