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,

float startAngle,

float sweepAngle,

boolean useCenter,

Paint paint)
绘制弧面或弧线。对于绘制对应图形的填充面,还是图形的轮廓线,这在于画笔Paint中的setStyle。
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);

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);
效果图从上至下,分别对应方法1-3


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,

400f, 400f, 250f, 560f,

250f, 560f, 400f, 800f,

400f, 800f, 280f, 880f};
//有选择地绘制直线
canvas.drawLines(pts, 4, 8, mPaint);
跳过前4个数据,绘制后面8的数据,即绘制了第二第三个点:


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中加入Arc
RectF arcRecF = new RectF(0, 0, 500, 500);
path.addArc(arcRecF, 0, 135);
canvas.drawPath(path, mPaint);
更多Path(宝藏,可继续挖掘),详见博客android绘图之Path总结

drawPoint

void drawPoint (float x,

float y,

Paint paint)
绘制点,x,y分别是点坐标

void drawPoints (float[] pts,

int offset,

int count,

Paint paint)
void drawPoints (float[] pts,

Paint paint)
drawPoints与drawLines类似

drawRGB

void drawRGB (int r,

int g,

int b)
RGB绘制画布颜色,取值也是0~255

drawRect

void drawRect (float left,

float top,

float right,

float bottom,

Paint paint)
绘制矩形,前四个参数分别表示矩形的左,顶,右,低

void drawRect (Rect r,Paint paint)
void drawRect (RectF rect,Paint paint)
Rect 和 RectF区别是Rect初始化 是int,RectF 是left

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,

float hOffset,

float vOffset,

Paint paint)
void drawTextOnPath (char[] text,

int index,

int count,

Path path,

float hOffset,

float vOffset,

Paint paint)
沿着Path绘制一段文字
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
各种裁剪组合模式,有六个枚举常量,如下图,红色即组合裁剪的区域。

// 填充颜色
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     DIFFERENCE

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);


红色矩形比绿色缩小的一半

//方法2
void scale (float sx,

float sy,

float px,

float py)
px和py 分别为缩放的基准点,看scale源码可知基准点平移了:

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)
int save ()
void restore ()
save 保存当前矩阵,剪辑到一个私有堆栈。save()方法之后的代码,可以调用Canvas的平移、放缩、旋转、裁剪等操作
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总结



欢迎长按上图识别图中二维码或者微信扫一扫关注我的公众号。


    关注 吴小龙同学


微信扫一扫关注公众号

0 个评论

要回复文章请先登录注册