Canvas类保存“draw”调用。 要绘制一些东西,你需要4个基本组件:Bitmap来保存像素,Canvas来承载绘图调用(写入位图),绘图基元(例如Rect,Path,text,Bitmap),以及Paint来描述绘图的颜色和样式。
clipPath(Path path,Region.Op op):根据指定的Path路径裁剪Canvas。
Path path:指定的路径;
Region.Op op:裁剪的运算规则。
clipRect(float left,float top,float right,float bottom,Region.Op op):根据指定的Rect裁剪Canvas。
float left:左边偏移量;
float top:上边偏移量;
float right:右边偏移量;
float bottom:下边偏移量;
Region.Op op:裁剪的运算规则。
clipRect(Rect rect,Region.Op op):根据指定的Rect裁剪Canvas。
Rect rect:矩阵,包含了左、上、右、下坐标;
Region.Op op:裁剪的运算规则。
clipRegion(Region region,Region.Op op):根据指定的Region裁剪Canvas。
Region region:由数个Rect组成的对象;
Region.Op op:裁剪的运算规则。
clip方法都是针对Canvas裁剪而非Canvas中的内容,每次clip方法都相当于新建了一层画布并裁剪。
上述3个clip方法中都会涉及到Region.Op枚举类。
下面对这个枚举类做一个解释:
为了方便说明,把第一次clipRect的绘制范围设为A,第二次clipRect设定的范围设为B。
Op.DIFFERENCE:旧画布减去新旧两块画布的交集,即只显示A -(A∩B);
Op.REVERSE_DIFFERENCE:新画布减去新旧两块画布的交集,即显示B-(A∩B)+A;
Op.INTERSECT,新的画布和当前画布的共同区域,即显示A+(A∩B);
Op.REPLACE,不论A和B的集合状况,B的范围将全部进行显示,如果和A有交集,则将覆盖A的交集范围,如果A和B不相交,那各自都会完全显示;
Op.UNION,即A和B的并集范围,即两者所包括的范围的绘制内容都会被显示;
Op.XOR,新旧两块画布的并集减去两块画布的交集,即(A∪B)-(A∩B);
/**
* 测试clip方法
*/
// 简单测试clip方法
Rect rect = new Rect(0, 0, 600, 600); // 绘制了(0,0)->(600,600)的矩形
paint.setColor(Color.BLACK);
canvas.clipRect(0,0,300,300);// 裁剪出(0,0)->(300,300)的矩形
canvas.drawRect(rect, paint);
// 测试clip方法的运算规则
Path path = new Path();
path.addRect(0, 0, 200, 200, Path.Direction.CCW);
paint.setColor(Color.RED);
canvas.drawPath(path, paint); // 绘制(0,0)->(200,200)的红色矩阵
// 测试Region.Op.DIFFERENCE的效果
// 在上面画布绘制上基础上裁剪掉指定的区域,后面的绘制的在这块区域内显示上面绘制的内容
ccanvas.clipRect(150, 150, 450, 450, Region.Op.DIFFERENCE);
paint.setColor(Color.YELLOW);
canvas.drawRect(50, 50, 350, 350, paint);// 绘制(50,50)->(350,350)的黄色矩阵
// 测试Region.Op.REVERSE_DIFFERENCE的效果
// 和原来的画布结合成一个整块的画布,并将新画布中重合的部分给除掉
canvas.clipRect(150, 150, 450, 450, Region.Op.REVERSE_DIFFERENCE);
paint.setColor(Color.YELLOW);
canvas.drawRect(50, 50, 350, 350, paint);// 绘制(50,50)->(350,350)的黄色矩阵
// 测试Region.Op.INTERSECT的效果
// 旧画布加上新的画布和当前画布的共同区域
canvas.clipRect(150, 150, 450, 450, Region.Op.INTERSECT);
paint.setColor(Color.YELLOW);
canvas.drawRect(50, 50, 350, 350, paint);// 绘制(50,50)->(350,350)的黄色矩阵
// 测试Region.Op.REPLACE的效果
// 不论新旧两块canvas的相交情况,新canvas一定完全显示;相交的部分新的会覆盖掉旧的。如果两个canvas不相交,那各自都会完全显示。
canvas.clipRect(150, 150, 450, 450, Region.Op.REPLACE);
paint.setColor(Color.YELLOW);
canvas.drawRect(50, 50, 350, 350, paint);// 绘制(50,50)->(350,350)的黄色矩阵
// 测试Region.Op.UNION的效果
// 新画布和原来的画布结合成一个整块的画布,后面绘制的图形都将在两个画布上进行显示。即:新旧两块画布的并集。
canvas.clipRect(150, 150, 450, 450, Region.Op.UNION);
paint.setColor(Color.YELLOW);
canvas.drawRect(50, 50, 350, 350, paint);// 绘制(50,50)->(350,350)的黄色矩阵
// 测试Region.Op.XOR的效果
// 新旧两块画布的并集减去两块画布的交集。
canvas.clipRect(150, 150, 450, 450, Region.Op.XOR);
paint.setColor(Color.YELLOW);
canvas.drawRect(50, 50, 350, 350, paint);// 绘制(50,50)->(350,350)的黄色矩阵
/**
* 测试drawArc方法
*/
paint.setColor(Color.BLACK);
paint.setAntiAlias(true);//消除锯齿,但是会减慢绘制速度
paint.setStyle(Paint.Style.FILL);// 设置画笔的风格
// 设置绘制区域
RectF rect = new RectF(50, 50, 200, 200);
// 先绘制黑色背景
canvas.drawRect(rect, paint);
// 绘制扇形
paint.setColor(Color.RED);
canvas.drawArc(rect, 0, 90, true, paint);// 设置使用中心
// 绘制扇形
paint.setColor(Color.RED);
canvas.drawArc(rect, 0, 90, false, paint);// 设置不使用中心
// 绘制扇形
paint.setStyle(Paint.Style.STROKE);// 设置画笔的风格
paint.setStrokeWidth(5);// 设置画笔风格为STROKE时,必须设置StrokeWidth
paint.setColor(Color.RED);
canvas.drawArc(rect, 0, 90, true, paint);// 设置使用中心
将画笔风格设置为STROKE,设置使用中心,则绘制出了一个空心的扇形。并且如果大家仔细看的话,发现空心扇形已经超出了黑色背景的边缘,所以大家使用STROKE时需要考虑到StrokeWidth的宽度对绘制图的影响。
// 绘制扇形
paint.setStyle(Paint.Style.STROKE);// 设置画笔的风格
paint.setStrokeWidth(5);
paint.setColor(Color.RED);
canvas.drawArc(rect, 0, 90, false, paint);// 设置不使用中心
/**
* 测试ARGB
*/
canvas.clipRect(50, 50, 250, 250);
canvas.drawARGB(200, 150, 60, 120);
drawBitmap(Bitmap bitmap, float left, float top, Paint paint) :绘制位图。
Bitmap bitmap:位图对象;
float left:位图在Canvas上偏移左边的位置;
float top:位图在Canvas上偏移顶部的位置;
Paint paint:画笔,定义绘制的颜色、Style风格等属性。
drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) :绘制位图。
Bitmap bitmap:位图对象;
Rect src:是对图片进行裁剪,若是空null则显示整个图片;
Rect dst:位图在Canvas上显示的区域;
Paint paint:画笔,定义绘制的颜色、Style风格等属性。
drawCircle(float cx, float cy, float radius, Paint paint):绘制圆形。
float cx:圆心的x坐标;
float cy:圆心的y坐标;
float radius:圆的半径;
Paint paint:画笔,定义绘制的颜色、Style风格等属性。
/**
* 测试drawCircle方法
*/
paint.setColor(Color.GREEN);
paint.setAntiAlias(true);//消除锯齿,但是会减慢绘制速度
paint.setStyle(Paint.Style.FILL);// 设置画笔的风格
// 绘制圆形
canvas.drawCircle(100, 100, 50, paint);
paint.setColor(Color.GREEN);
paint.setAntiAlias(true);//消除锯齿,但是会减慢绘制速度
paint.setStyle(Paint.Style.STROKE);// 设置画笔的风格
paint.setStrokeWidth(5);
// 绘制圆形
canvas.drawCircle(100, 100, 50, paint);
这里将画笔的风格设置为STROKE,即空心模式,则绘制了一个圆环。这里同样需要注意的是StrokeWidth的宽度对绘制图的影响。
drawColor(int color, PorterDuff.Mode mode):绘制颜色,但是要制定一个mode。
int color:颜色值
PorterDuff.Mode mode:绘制颜色的模式
drawLine(float startX, float startY, float stopX, float stopY, Paint paint):绘制直线。
float startX:直线的起点x坐标;
float startY:直线的起点y坐标;
float stopX:直线的终点x坐标;
float stopY:直线的终点y坐标;
Paint paint:画笔,定义绘制的颜色、Style风格等属性。
/**
* 测试drawLine
*/
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.STROKE);// 这里也可以设为FILL,效果是一样的
paint.setStrokeWidth(10);
canvas.drawLine(50, 50, 150, 250, paint);
/**
* 测试drawLines
*/
paint.setColor(Color.BLUE);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(5);
float[] pts = {20, 30, 100, 50, 50, 30, 90, 150, 45, 80, 120, 30};
canvas.drawLines(pts, paint);
/**
* 测试drawOval方法
*/
paint.setColor(Color.RED);
paint.setAntiAlias(true);//消除锯齿,但是会减慢绘制速度
paint.setStyle(Paint.Style.FILL);// 设置画笔的风格
// 设置绘制区域
RectF rect = new RectF(50, 50, 200, 100);
canvas.drawOval(rect,paint);
paint.setStyle(Paint.Style.STROKE);// 设置画笔的风格
paint.setStrokeWidth(5);
// 设置绘制区域
RectF rect = new RectF(50, 50, 200, 100);
canvas.drawOval(rect,paint);
drawPaint(Paint paint):绘制背景,效果类似于drawColor。
Paint paint:画笔,定义绘制的颜色、Style风格等属性。
drawPath(Path path, Paint paint) :绘制指定的路径。
Path path:指定的路径;
Paint paint:画笔,定义绘制的颜色、Style风格等属性。
/**
* 测试drawPath,绘制出一个三角形
*/
paint.setColor(Color.RED);
paint.setAntiAlias(true);//消除锯齿,但是会减慢绘制速度
paint.setStyle(Paint.Style.FILL);// 设置画笔的风格
Path path = new Path();
path.moveTo(50,50);
path.lineTo(100,50);
path.lineTo(75,100);
path.close();
canvas.drawPath(path,paint);
/**
* 测试drawPoint,绘制出一个点
*/
paint.setColor(Color.RED);
paint.setAntiAlias(true);//消除锯齿,但是会减慢绘制速度
paint.setStyle(Paint.Style.STROKE);// 设置画笔的风格
paint.setStrokeWidth(20);
paint.setStrokeCap(Paint.Cap.ROUND);// 设置画笔的形状
canvas.drawPoint(50,50,paint);
paint.setColor(Color.GREEN);
paint.setStrokeCap(Paint.Cap.BUTT);// 设置画笔的形状
canvas.drawPoint(80,50,paint);
paint.setColor(Color.BLUE);
paint.setStrokeCap(Paint.Cap.SQUARE);// 设置画笔的形状
canvas.drawPoint(120,50,paint);
drawPoints(float[] pts, int offset, int count, Paint paint):绘制多个点,需要在paint中定义画笔宽度(setStrokeWidth)、以及形状(setStrokeCap)。
float[] pts:多条点的坐标,每条点占用2个数据;
int offset:跳过的数据的个数;
int count:最终实际参与绘制的数据个数;
Paint paint:画笔,定义绘制的颜色、Style风格等属性。
drawPosText(char[] text, int index, int count, float[] pos, Paint paint) :按照指定点的坐标绘制文本。(方法已过时)
char[] text:需要绘制的文本数组
int index:需要绘制的第一个字符位置;
int count:实际参与绘制的数据个数;
float[] pos:被绘制文本的坐标,每个字占用2个数据;
Paint paint:画笔,定义绘制的颜色、Style风格等属性。
drawPosText(String text, float[] pos, Paint paint):按照指定点的坐标绘制文本。(方法已过时)
String text:需要绘制的文本字符串
float[] pos:被绘制文本的坐标,每个字占用2个数据;
Paint paint:画笔,定义绘制的颜色、Style风格等属性。
/**
* 测试drawPosText
*/
paint.setColor(Color.RED);
paint.setAntiAlias(true);//消除锯齿,但是会减慢绘制速度
paint.setStyle(Paint.Style.STROKE);// 设置画笔的风格
paint.setStrokeWidth(2);
paint.setTextSize(50);
String text = "Test";
float[] pos = {50, 50, 100, 100, 150, 50, 200, 100};
canvas.drawPosText(text, pos, paint);
drawRect(float left, float top, float right, float bottom, Paint paint):绘制矩形。
float left:左边偏移量;
float top:上边偏移量;
float right:右边偏移量;
float bottom:下边偏移量;
Paint paint:画笔,定义绘制的颜色、Style风格等属性。
drawRect(Rect r, Paint paint):绘制矩形。
Rect r:矩形在Canvas上显示的区域;
Paint paint:画笔,定义绘制的颜色、Style风格等属性。
drawRGB(int r, int g, int b):绘制Canvas背景色。
int r:red色彩空间
int g:green色彩空间
int b:blue色彩空间
drawRoundRect(RectF rect, float rx, float ry, Paint paint):绘制圆角矩形。
RectF rect:指定的绘制区域
float rx:x方向的圆角弧度;
float ry:y方向的圆角弧度;
Paint paint:画笔,定义绘制的颜色、Style风格等属性。
/**
* 测试drawRoundRect
*/
paint.setColor(Color.RED);
paint.setAntiAlias(true);//消除锯齿,但是会减慢绘制速度
paint.setStyle(Paint.Style.FILL);// 设置画笔的风格
RectF rectF = new RectF(50, 50, 200, 200);// 绘制区域
canvas.drawRoundRect(rectF,10,40,paint);
可能看的不是很清楚,但是还是能看到x方向的弧度与y方向的弧度大小是不一样的,x方向比较尖锐。
drawText(char[] text, int index, int count, float x, float y, Paint paint):绘制文本。
char[] text:需要绘制的文本数组
int index:需要绘制的第一个字符位置;
int count:实际参与绘制的字符个数;
float x:绘制的点的x坐标;
float y:绘制的点的y坐标,默认是文本的baseLine的y坐标,而不是上沿的y坐标;
Paint paint:画笔,定义绘制的颜色、Style风格等属性。
drawText(String text, float x, float y, Paint paint):绘制文本。
String text:需要绘制的文本字符串
float x:绘制的点的x坐标;
float y:绘制的点的y坐标,默认是文本的baseLine的y坐标,而不是上沿的y坐标;
Paint paint:画笔,定义绘制的颜色、Style风格等属性。
drawText(String text, int start, int end, float x, float y, Paint paint):绘制文本。
String text:需要绘制的文本字符串
int start:开始的字符位置(包含)
int end:结束的字符位置(不含)
float x:绘制的点的x坐标;
float y:绘制的点的y坐标,默认是文本的baseLine的y坐标,而不是上沿的y坐标;
Paint paint:画笔,定义绘制的颜色、Style风格等属性。
/**
* 测试drawText
*/
String text = "12345678";
Rect bound = new Rect();
// 获取到text的区域范围,从而可以获取到text的宽高
paint.getTextBounds(text, 0, text.length(), bound);
paint.setTextSize(30);
paint.setColor(Color.RED);
canvas.drawText(text, 50, 50 + bound.height(), paint);// y指的是text的baseLine的偏移量
drawTextOnPath(char[] text, int index, int count, Path path, float hOffset, float vOffset, Paint paint):依据路径排版文本。
char[] text:需要绘制的文本数组
int index:需要绘制的第一个字符位置;
int count:实际参与绘制的字符个数;
Path path:指定的路径;
float hOffset:水平方向的偏移量;
float vOffset:垂直方向的偏移量;
Paint paint:画笔,定义绘制的颜色、Style风格等属性。
drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint):依据路径排版文本。
String text:需要绘制的文本字符串
Path path:指定的路径;
float hOffset:水平方向的偏移量;
float vOffset:垂直方向的偏移量;
Paint paint:画笔,定义绘制的颜色、Style风格等属性。
/**
* 测试drawTextOnPath
*/
Path path = new Path();
path.addRect(50, 50, 350, 350, Path.Direction.CW);// 添加一个矩形,并设置矩形的方向为顺时针方向
paint.setColor(Color.GREEN);
paint.setAntiAlias(true);//消除锯齿,但是会减慢绘制速度
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(3);
canvas.drawPath(path,paint);// 先绘制出矩形,便于观察
String text = "canvas.drawTextOnPath";
paint.setTextSize(50);
paint.setColor(Color.RED);
canvas.drawTextOnPath(text,path,50,10,paint);
现在是顺时针方向,如果设置Path.Direction.CCW就是逆时针方向。
getSaveCount():返回栈中保存的状态,值等于 save()调用次数-restore()调用次数
restore():回到上一个save调用之前的状态,如果restore调用的次数大于save方法,会出错。
restoreToCount(int saveCount):回到任何一个save()方法调用之前的状态。
int saveCount:某一个save()方法调用的地方;
save():保存当前的matrix和clip到私有的栈中(Skia内部实现)。任何matrix变换和clip操作都会在调用restore的时候还原。
save(int saveFlags):传入一个标志,来表示当restore 的时候,哪些参数需要还原。该参数定义在Canvas中,参照下面。save()方法默认的是还原matrix和clip,但是可以使用这个方法指定哪些需要还原。并且只有指定matrix和clip才有效,其余的几个参数是用于saveLayer()和saveLayerAlpha()方法的。
int saveFlags:指定需要还原哪些参数;
MATRIX_SAVE_FLAG:需要还原Matrix;
CLIP_SAVE_FLAG:需要还原Clip;
HAS_ALPHA_LAYER_SAVE_FLAG:图层的 clip 标记;
FULL_COLOR_LAYER_SAVE_FLAG:图层的 color 标记;
CLIP_TO_LAYER_SAVE_FLAG:图层的 clip 标记,在saveLayer 和 saveLayerAlpha Android强烈建议必须加上他;
ALL_SAVE_FLAG:还原所有,一般情况都是使用这个;
saveLayer(float left, float top, float right, float bottom, Paint paint, int saveFlags):保存当前图层到栈中。
float left:左边偏移量;
float top:上边偏移量;
float right:右边偏移量;
float bottom:下边偏移量;
Paint paint:画笔,定义绘制的颜色、Style风格等属性。
int saveFlags:指定需要还原哪些参数;
saveLayer(RectF bounds, Paint paint, int saveFlags):保存当前图层到栈中。
RectF bounds:图层所在的区域;
Paint paint:画笔,定义绘制的颜色、Style风格等属性。
int saveFlags:指定需要还原哪些参数;
saveLayerAlpha(float left, float top, float right, float bottom, int alpha, int saveFlags):本身和save方法差不多,但是它单独分配了一个画布用于绘制图层。它定义了一个画布区域(可设置透明度),此方法之后的所有绘制都在此区域中绘制,直到调用canvas.restore()方法。
float left:左边偏移量;
float top:上边偏移量;
float right:右边偏移量;
float bottom:下边偏移量;
int alpha:透明度;
int saveFlags:指定需要还原哪些参数;
saveLayerAlpha(RectF bounds, int alpha, int saveFlags):本身和save方法差不多,但是它单独分配了一个画布用于绘制图层。它定义了一个画布区域(可设置透明度),此方法之后的所有绘制都在此区域中绘制,直到调用canvas.restore()方法。
RectF bounds:图层所在的区域;
int alpha:透明度;
int saveFlags:指定需要还原哪些参数;
rotate(float degrees, float px, float py):绕x,y支点旋转Canvas,默认绕(0,0)点。
float degrees:旋转角度;
float px:支点的x坐标;
float py:支点的y坐标;
scale(float sx, float sy, float px, float py):放大Canvas。
float sx:x轴方向放大倍数;
float sy:y轴方向放大倍数;
float px:支点的x坐标;
float py:支点的y坐标;
setBitmap(Bitmap bitmap):设置Canvas到指定的Bitmap位图中绘制。
Bitmap bitmap:位图。
translate(float dx, float dy):Canvas平移到指定的点。
float dx:平移到的点的x坐标;
float dy:平移到的点的y坐标;
目前Canvas的总结就这样,后面我会持续更新Canvas各方法的应用场景与应用方法。对Paint、Path的总结即将开始,敬请期待。。。