Android 画布Canvas
写完 Android 画笔Paint,自然少不了Canvas画布,本文延续上篇风格,一一来过Canvas API。...
写完 Android 画笔Paint,自然少不了Canvas画布,本文延续上篇风格,一一来过Canvas API。
绘制方法
以drawXXX为主的绘制方法,api如下:drawARGB
void drawARGB (int a,int r,int g,int b)统一颜色绘制,四个参数取值范围0~255
drawArc
void drawArc (RectF oval,绘制弧面或弧线。对于绘制对应图形的填充面,还是图形的轮廓线,这在于画笔Paint中的setStyle。
float startAngle,
float sweepAngle,
boolean useCenter,
Paint paint)
oval:矩形;
startAngle:起点角度,0度的角度对应于0度的几何角(在手表3点钟);
sweepAngle:顺时针扫过的角度;
useCenter:弧面或弧线;
paint:画笔
弧面
RectF rectF = new RectF(100f, 100f, 500f, 500f);
canvas.drawArc(rectF, 0, 150, true, mPaint);
弧线
RectF rectF = new RectF(100f, 100f, 500f, 500f);
canvas.drawArc(rectF, 0, 150, false, mPaint);
drawBitmap
绘制使用指定的矩阵的位图。//方法1例子代码
void drawBitmap (Bitmap bitmap,
float left,
float top,
Paint paint)
//方法2
void drawBitmap (Bitmap bitmap,
Rect src,
Rect dst,
Paint paint)
//方法3
void drawBitmap (Bitmap bitmap,
Matrix matrix,
Paint paint)
mBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.logo);效果图从上至下,分别对应方法1-3
canvas.drawBitmap(mBitmap, 0, 0, mPaint);
//绘制Bitmap的一部分,并对其拉伸
//srcRect绘制Bitmap的哪一部分
Rect src = new Rect(0, 0, mBitmap.getWidth(), mBitmap.getHeight() / 3);
//dstRecF绘制的Bitmap拉伸到哪里
RectF dst = new RectF(0, mBitmap.getHeight(), canvas.getWidth(), mBitmap.getHeight() + 200);
canvas.drawBitmap(mBitmap, src, dst, mPaint);
Matrix matrix = new Matrix();
matrix.postTranslate(0, mBitmap.getHeight() + 200);
canvas.drawBitmap(mBitmap, matrix, mPaint);
drawBitmapMesh
void drawBitmapMesh (Bitmap bitmap,绘制网格顶点被均匀地分布在该位图
int meshWidth,
int meshHeight,
float[] verts,
int vertOffset,
int[] colors,
int colorOffset,
Paint paint)
bitmap:位图
meshWidth:横向上把该源位图划成成多少格
meshHeight:竖向上把该源位图划成成多少格
verts:长度为(meshWidth + 1) (meshHeight + 1) 2的数组,它记录了扭曲后的位图各顶点位置
vertOffset:控制verts数组中从第几个数组元素开始才对bitmap进行扭曲
colors:可以为null,指定在每个顶点,其值由对应的位图颜色相乘内插的颜色。如果不为空,必须有至少(meshWidth+ 1)*(meshHeight+ 1)+ colorOffset数组中的值。
colorOffset int: Number of color elements to skip before drawing
paint:画笔,可以为null
效果参考博客 Android Canvas的drawBitmapMesh实现扭曲图像
drawCircle
void drawCircle (float cx,绘制圆
float cy,
float radius,
Paint paint)
cx,cy代表圆心的坐标
radius圆的半径
paint画笔
canvas.drawCircle(500f, 500f, 200, mPaint);
drawColor
void drawColor (int color)设置画布颜色
drawLine
void drawLine (float startX,画线
float startY,
float stopX,
float stopY,
Paint paint)
void drawLines (float[] pts,
Paint paint)
void drawLines (float[] pts,
int offset,
int count,
Paint paint)
方法1
startX,startY起点坐标
stopX,stopY终点坐标
paint画笔
方法2
pts:绘制直线的端点数组,每条直线占用4个数据,即起终点坐标。
paint:绘制直线所使用的画笔。
方法2
pts:绘制直线的端点数组,每条直线占用4个数据,即起终点坐标。
offset:跳过的数据个数,取值为4的倍数。
count:实际参与绘制的数据个数。
paint:绘制直线所使用的画笔。
canvas.drawLine(100f,100f,500f,500f,mPaint);
float[] pts = {100f, 100f, 400f, 400f,
400f, 400f, 250f, 560f,
250f, 560f, 400f, 800f,
400f, 800f, 280f, 880f};
canvas.drawLines(pts, mPaint);
float[] pts = {100f, 100f, 400f, 400f,跳过前4个数据,绘制后面8的数据,即绘制了第二第三个点:
400f, 400f, 250f, 560f,
250f, 560f, 400f, 800f,
400f, 800f, 280f, 880f};
//有选择地绘制直线
canvas.drawLines(pts, 4, 8, mPaint);
drawOval
void drawOval (RectF oval,Paint paint)绘制椭圆
RectF rectF = new RectF(100f, 100f, 600f, 500f);
//等同于圆的效果
//RectF rectF = new RectF(100f, 100f, 500f, 500f);
canvas.drawOval(rectF, mPaint);
drawPath
void drawPath (Path path,Paint paint)例子
Path path = new Path();更多Path(宝藏,可继续挖掘),详见博客android绘图之Path总结
//向Path中加入Arc
RectF arcRecF = new RectF(0, 0, 500, 500);
path.addArc(arcRecF, 0, 135);
canvas.drawPath(path, mPaint);
drawPoint
void drawPoint (float x,绘制点,x,y分别是点坐标
float y,
Paint paint)
void drawPoints (float[] pts,drawPoints与drawLines类似
int offset,
int count,
Paint paint)
void drawPoints (float[] pts,
Paint paint)
drawRGB
void drawRGB (int r,RGB绘制画布颜色,取值也是0~255
int g,
int b)
drawRect
void drawRect (float left,绘制矩形,前四个参数分别表示矩形的左,顶,右,低
float top,
float right,
float bottom,
Paint paint)
void drawRect (Rect r,Paint paint)Rect 和 RectF区别是Rect初始化 是int,RectF 是left
void drawRect (RectF rect,Paint paint)
canvas.drawRect(100f,100f,500f,500f,mPaint);
drawRoundRect
void drawRoundRect (RectF rect,绘制圆矩形
float rx,
float ry,
Paint paint)
rx:圆角x方向的半径
ry:圆角y方向的半径
RectF rectF = new RectF(100f, 100f, 500f, 500f);
canvas.drawRoundRect(rectF, 50, 150, mPaint);
drawText
void drawText (CharSequence text,绘制文本
int start,
int end,
float x,
float y,
Paint paint)
void drawText (String text,
float x,
float y,
Paint paint)
void drawText (String text,
int start,
int end,
float x,
float y,
Paint paint)
start:指的文本从哪个开始;end:文本结束的位置;x,y:文本起点
mPaint.setTextSize(50);
String text = "我的微信公众号:吴小龙同学";
canvas.drawText(text, 2, text.length(), 100, 100, mPaint)
canvas.drawText("我的微信公众号:吴小龙同学", 100, 400, mPaint);
drawTextOnPath
void drawTextOnPath (String text,沿着Path绘制一段文字
Path path,
float hOffset,
float vOffset,
Paint paint)
void drawTextOnPath (char[] text,
int index,
int count,
Path path,
float hOffset,
float vOffset,
Paint paint)
hOffset : 与路径起始点的水平偏移距离
vOffset : 与路径中心的垂直偏移量
Path path = new Path();
//Path.Direction.CW,沿外环;Path.Direction.CCW,沿内环
path.addCircle(500, 500, 200, Path.Direction.CW);
mPaint.setTextSize(50);
// 绘制路径
canvas.drawPath(path, mPaint);
String text = "我的微信公众号:吴小龙同学";
canvas.drawTextOnPath(text, path, 0f, 0f, mPaint);
drawVertices
void drawVertices (Canvas.VertexMode mode,绘制顶点数组
int vertexCount,
float[] verts,
int vertOffset,
float[] texs,
int texOffset,
int[] colors,
int colorOffset,
short[] indices,
int indexOffset,
int indexCount,
Paint paint)
微信公众号
文章又是太长,中场休息会,然后打个广告先~嘿嘿~裁剪方法
以clipXXX为主的clipPath
boolean clipPath (Path path,裁剪路径
Region.Op op)
boolean clipPath (Path path)
op:各种裁剪组合模式,有六个枚举常量,下有详解
Path path = new Path();
RectF arcRecF = new RectF(0, 0, 500, 500);
path.addArc(arcRecF, 0, 135);
canvas.clipPath(path);
canvas.drawColor(Color.RED);
有图可知,画布已经是红区区域了。
clipRect
boolean clipRect (float left,裁剪矩形
float top,
float right,
float bottom,
Region.Op op)
boolean clipRect (RectF rect)
boolean clipRect (int left,
int top,
int right,
int bottom)
boolean clipRect (RectF rect,
Region.Op op)
boolean clipRect (Rect rect)
canvas.clipRect(100, 100, 400, 500);
canvas.drawColor(Color.RED);
有图可知,画布已经是红区矩形区域了。
Region.Op
各种裁剪组合模式,有六个枚举常量,如下图,红色即组合裁剪的区域。
// 填充颜色Region.Op DIFFERENCE
canvas.drawColor(Color.BLUE);
canvas.save();
canvas.clipRect(100, 100, 400, 500);
canvas.clipRect(200, 200, 600, 600, Region.Op.DIFFERENCE);
canvas.drawColor(Color.RED);
canvas.restore();
// 绘制和裁剪一样的矩形便于观察
canvas.drawRect(100, 100, 400, 500, mPaint);
canvas.drawRect(200, 200, 600, 600, mPaint);
Region.Op INTERSECT
Region.Op REPLACE
Region.Op REVERSE_DIFFERENCE
Region.Op UNION
Region.Op XOR
变换方法
rotate,scale、skew、translate旋转、缩放、错切、平移
rotate
void rotate (float degrees)画布的旋转
void rotate (float degrees,
float px,
float py)
degrees:顺时针旋转的角度
px和py 基准点平移,默认起点(0,0)
canvas.drawColor(Color.BLUE);
canvas.drawRect(new Rect(0, 0, 400, 400), mPaint);
mPaint.setColor(Color.YELLOW);
canvas.rotate(45);
canvas.drawRect(new Rect(0, 0, 400, 400), mPaint);
scale
//方法1画布的缩放
void scale (float sx, float sy)
sx、sy是x、y方向上缩放的倍数
canvas.drawColor(Color.BLUE);
mPaint.setColor(Color.GREEN);
canvas.drawRect(0, 0, 400, 500, mPaint);
canvas.scale(0.5f, 0.5f);
mPaint.setColor(Color.RED);
canvas.drawRect(0, 0, 400, 500, mPaint);
红色矩形比绿色缩小的一半
//方法2px和py 分别为缩放的基准点,看scale源码可知基准点平移了:
void scale (float sx,
float sy,
float px,
float py)
public final void scale(float sx, float sy, float px, float py) {例子
translate(px, py);
scale(sx, sy);
translate(-px, -py);
}
canvas.drawColor(Color.BLUE);
mPaint.setColor(Color.GREEN);
canvas.drawRect(0, 0, 400, 500, mPaint);
// 保存画布状态
canvas.save();
canvas.scale(0.5f, 0.5f);
mPaint.setColor(Color.RED);
canvas.drawRect(0, 0, 400, 500, mPaint);
canvas.restore();
canvas.scale(0.5f, 0.5f, 200, 200);
mPaint.setColor(Color.WHITE);
canvas.drawRect(0, 0, 400, 500, mPaint);
白色就是平移后的效果
skew
void skew (float sx,float sy)画布的错切
float sx:将画布在x方向上倾斜相应的角度,sx为倾斜角度的tan值;
float sy:将画布在y轴方向上倾斜相应的角度,sy为倾斜角度的tan值;
比如在X轴方向上倾斜45度,tan45=1;
translate
void translate (float dx,float dy)画布的平移
dx,dy平移量
canvas.drawColor(Color.BLUE);
canvas.translate(100, 100);
canvas.drawRect(new Rect(0, 0, 400, 400), mPaint);
坐标从起点(0,0)变成了(100,100)
画布锁定和还原
以saveXXX和restoreXXX构成的画布锁定和还原int save (int saveFlags)save 保存当前矩阵,剪辑到一个私有堆栈。save()方法之后的代码,可以调用Canvas的平移、放缩、旋转、裁剪等操作
int save ()
void restore ()
restore 恢复Canvas之前保存的状态
save和restore要配对使用,restore可以比save少,但不能多,如果restore调用次数比save多,会引发Error。
例子源码
https://github.com/WuXiaolong/AndroidSamples/blob/master/app/src/main/java/com/wuxiaolong/androidsamples/paintcanvas/CanvasView.java鸣谢
官网api自定义控件其实很简单5/12
Canvas之translate、scale、rotate、skew方法讲解!
android绘图之Path总结
欢迎长按上图→识别图中二维码或者微信扫一扫关注我的公众号。
关注 吴小龙同学
微信扫一扫关注公众号