前言

Android 中的Canvas相当于是画布,通过画笔绘制几何图形,文本,路径和位图等;

常用Api分类:

绘制

变换

状态保存/恢复

简单看下第一种分类,不做重点介绍

绘制相关

void drawText(String text,int start, int end,Paint paint) //指定坐标 绘制文字

void drawPoint(float x, float y,Paint paint) //指定坐标 绘制点

void drawLine(float startX, float startY,float endX, float endY,Paint paint) //指定起始点,结束点 绘制连线

void drawPath(Path path,Paint paint) //指定path 绘制连线

void drawBitmap(Bitmap bitmap,float left,float top,Paint paint) //指定坐标,绘制位图

void drawCircle(float cx, float cy, float radius, Paint paint) //绘制圆形

void drawRect(RectF rect,Paint paint) //绘制矩形

等等等...

位置/形状 变换相关

void translate(float dx, float dy) //平移操作

void scale(float sx, float sy) //缩放操作

void rotate(float degrees) //旋转操作

void skew(float sx, float sy) //倾斜操作

void clipXxx(...) //切割操作,参数指定区域内可以正常(继续)绘制

void clipOutXxx(...) //反向切割操作,参数指定区域内不可以正常(继续)绘制

void setMatrix(Matrix matrix) :可通过matrix实现平移,缩放,旋转等操作

translate(float dx, float dy)平移操作,操作画布平移,相当于绘制的参考点坐标平移,从坐标系的角度来说比较简单,直接看图:

1b2033bd6d47

translate(float dx, float dy)

scale(float sx, float sy) 缩放操作,传入x,y方向的缩放比例,我们看下缩放前后对比(红色矩形为缩放前绘制,灰色矩形为缩放后绘制):

canvas.drawRect(200,200, 700,700, mPaint);

canvas.scale(0.5f, 0.5f);

mPaint.setColor(Color.GRAY);

canvas.drawRect(200,200, 700,700, mPaint);

1b2033bd6d47

scale(float sx, float sy)

scale(float sx, float sy) 操作对整个画布缩放操作,所以缩放后的绘制的矩形对比之前的,位置和大小都发生了变化,缩放操作还有个重载方法,需要四个参数void scale(float sx, float sy, float px, float py),我们看下前后对比

canvas.drawRect(200,200, 700,700, mPaint);

//先translate(px, py),再scale(sx, sy),再反向translate(px, py)

canvas.scale(0.5f, 0.5f,200,200);

mPaint.setColor(Color.GRAY);

canvas.drawRect(200,200, 700,700, mPaint);

1b2033bd6d47

void scale(float sx, float sy, float px, float py)

上述canvas.scale(0.5f, 0.5f,200,200)操作相当于一下三行代码:

//先translate(px, py)

canvas.translate(200, 200);

//再scale(sx, sy)

canvas.scale(0.5f, 0.5f);

//再反向translate(px, py)

canvas.translate(-200, -200);

rotate(float degrees) 旋转操作

还有一个重载方法:

void rotate(float degrees, float px, float py) //px, py表示旋转中心的坐标

默认顺时针旋转,直接看图:

canvas.drawRect(400, 400, 900, 900, mPaint);

canvas.rotate(45, 650, 650); //px, py表示旋转中心的坐标

mPaint.setColor(Color.GRAY);

canvas.drawRect(400, 400, 900, 900, mPaint);

1b2033bd6d47

rotate(float degrees, float px, float py)

void skew(float sx, float sy) 倾斜操作参数分别表示x,y方向倾斜的角度的tan值

canvas.drawRect(0,0, 400, 400, mPaint);

canvas.skew(1, 0); //在X方向倾斜45度,相当于Y轴逆时针旋转45

mPaint.setColor(Color.GRAY);

canvas.drawRect(0, 0, 400, 400, mPaint);

1b2033bd6d47

canvas.skew(1, 0)

如果在y方向倾斜45度的话

canvas.skew(0, 1); //在y方向倾斜45度, 相当于X轴顺时针旋转45

1b2033bd6d47

canvas.skew(0, 1)

void clipXxx(...) //切割操作,参数指定区域内可以正常(继续)绘制,不在赘述

void clipOutXxx(...) //反向切割操作,参数指定区域内不可以正常(继续)绘制,不在赘述

void setMatrix(Matrix matrix) 矩阵

Matrix类里面封装了一系列的api,比如:

Matrix matrix = new Matrix();

matrix.setTranslate(50,50);//平移

matrix.setRotate(45);//旋转

matrix.setScale(0.5f, 0.5f);//酸防

canvas.setMatrix(matrix);

canvas.drawRect(0,0,700,700, mPaint);

状态保存和恢复

调用了translate,scale,rotate,skew,clipRect等变换后,后续的操作都是基于

变换后的Canvas,都会受到影响,对于后续的操作很不方便。Canvas提供 了save, saveLayer, saveLayerAlpha, restore,restore ToCount来保存和恢复状态。

Canvas 的save()和restore()可以多次调用,Canvas内部维护了一个状态栈,每次save()操作会将当前状态压栈,每次restore()操作会将最上面的状态出栈,恢复到上次保存的状态

1b2033bd6d47

状态栈

我们也可以调用canvas.getSaveCount()获取当前保存的状态数,不进行任何的save()操作,getSaveCount()默认为1,调用canvas.getSaveCount()恢复到指定状态,参数为save()操作返回的int值

int state = canvas.save(); //保存状态1

Log.e("TAG", "onDraw: " + canvas.getSaveCount());

canvas.translate(70, 50);

canvas.drawRect(0, 0, 400, 400, mPaint);

canvas.save(); //保存状态2

canvas.restore(); //返回最新状态(状态2)

Log.e("TAG", "onDraw: " + canvas.getSaveCount());

mPaint.setColor(Color.BLUE);

canvas.drawRect(0, 0, 400, 400, mPaint);

canvas.restoreToCount(state);//手动指定的返回到状态1

Canvas的总结就到这里,使用Canvas实现小案例见:

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐