Canvas直面意思是画布,其实是一个封装了很多绘制方法的工具类。
绘制图像有四大基本的要素:
- 一个用来保存像素的Bitmap。
- 一个用来执行绘制操作的工具类Canvas。
- 绘制的东西,如指明画直线,画文字以及其他各种我们想绘制的东西。
- 绘制用的画笔Paint。
一、 Canvas基本Api介绍:
1、绘画用到的API:
画背景:
/**
*把整个画布用指定的颜色填充
* @param r 红色值
* @param g 绿色值
* @param b 蓝色值
*/
public void drawRGB(int r, int g, int b)
//同上,只是加上了alpha透明度
public void drawARGB(int a, int r, int g, int b)
public void drawColor(@ColorInt int color)//同上
/**
* 把整个画布根据指定的模式用指定的颜色填充
* @param color 颜色值
* @param mode 详细看PorterDuff.Mode
*/
public void drawColor(@ColorInt int color, @NonNull PorterDuff.Mode mode)
/**
* 使用指定的画笔,绘制一个尽可能大的矩形,即填充画布
* @param paint The paint used to draw onto the canvas
*/
public void drawPaint(@NonNull Paint paint)
drawPaint方法需要注意的是,Paint画笔需要指定颜色一个带有透明度的颜色值,才能用指定的颜色值填充画布,如果没有指定颜色值,那么通过此方法填充的将是黑色。
Paint paint = new Paint();
paint.setColor(0xaadc2e07);//如果没有指定颜色,那么画布就变成黑色了
canvas.drawPaint(paint);//画笔整个变为浅红色
下面继续介绍绘画Api:
**
画点:
**
/**
* 在指定的左边x,y处画一个点,点的大小与Paint设置的setStrokeWidth有关,如果不设置线宽,无法绘制点
*/*
public void drawPoint(float x, float y, @NonNull Paint paint);
/**
* 参数1:多个点,每两个值为一个点。最后个数不够两个的值,忽略。
* [x0 y0 x1 y1 x2 y2 ...]
*/
public void drawPoints(@Size(multiple=2) @NonNull float[] pts, @NonNull Paint paint);
/**
*从点坐标数组pts中offset位置开始取count个数值,然后在画布上画出这些点
* @param pts 点坐标数组,一个点2个值 [x0 y0 x1 y1 x2 y2 ...]
* @param offset 从pts数组offset位置开始取值
* @param count 在pts数组总共取多少个数值,offset+count<=pts.length
* @param paint 画笔
*/
public void drawPoints(@Size(multiple=2) float[] pts, int offset, int count,
@NonNull Paint paint)
如:
Paint paint = new Paint();
paint.setColor(0xaadc2e07);
float fp[]=new float[]{100,100,100,250,100,400,100,550};
paint.setStrokeWidth(100);
canvas.drawPoints(fp,3,4,paint);//从坐标点数组fp中脚标为3的地方开始取值,总共取4个值出来,即fp[3],fp[4],fp[5],fp[6]。
效果如下:
可以看到这里画出来的点是直角的,而不像我们印象中的点都是圆的,这是因为Paint画笔的影响。试想一下,如果我们的笔头是方的,那么画(就像盖章一样)出来的点,那也是方的,而如果我们的笔头是圆的,那么画出来的点也就是圆的了。通过Paint的setStrokeCap方法可以设置画笔笔帽样式。
Paint paint = new Paint();
paint.setColor(0xaadc2e07);
float fp[]=new float[]{100,100,100,250,100,400,100,550};
paint.setStrokeWidth(100);
paint.setStrokeCap(Paint.Cap.ROUND);//圆角
canvas.drawPoints(fp,3,4,paint);
效果:
针对setStrokeCap方法做几点说明:
- Paint有个setStrokeCap方法可以设置所画线段的时候两个端点的形状,即所画线段的帽端的形状,在下面讲到drawLine方法时会详细说明,其实setStrokeCap方法也会影响所画点的形状。Paint的setStrokeCap方法可以有三个取值:Paint.Cap.BUTT、Paint.Cap.ROUND和Paint.Cap.SQUARE。
- 默认情况下Paint的getStrokeCap的返回值是Paint.Cap.BUTT,默认画出来的点就是一个正方形,上图第一个点即是用BUTT作为帽端画的。
- 我们可以调用setStrokeCap方法设置Paint的strokeCap为Paint.Cap.ROUND时,画笔画出来的点就是一个圆形,上图即是用ROUND作为帽端画的。
- 调用调用setStrokeCap方法设置Paint的strokeCap为Paint.Cap.SQUARE时,画笔画出来的电也是一个正方形,与用BUTT画出来的效果在外观上相同
画线:
/**
* 根据指定的起始点坐标,画一条直线
*
* @param startX 起始点x坐标
* @param startY 起始点y坐标
* @param paint 画笔
*/
public void drawLine(float startX, float startY, float stopX, float stopY, Paint paint);
public void drawLines(@Size(multiple=4) @NonNull float[] pts, @NonNull Paint paint);
/**
*与drawPoints方法类似
* @param pts 直线坐标点 [x0 y0 x1 y1 x2 y2 ...]
* @param offset 坐标偏移值
* @param count 从pts中取多少个值
* @param paint 画笔
*/
public void drawLines(@Size(multiple=4) @NonNull float[] pts, int offset, int count,
@NonNull Paint paint)
画矩形:
/**
* 根据Rect指定的值画矩形,RectF与Rect的区别在于RectF存float型的坐标数据
*
* @param r 指定的矩形区域
* @param paint 画笔
*/
public void drawRect(@NonNull Rect r, @NonNull Paint paint);
public void drawRect(@NonNull RectF rect, @NonNull Paint paint);
/**
* 由指定的矩形的四个顶点画矩形
* @param left The left side of the rectangle to be drawn
* @param top The top side of the rectangle to be drawn
* @param right The right side of the rectangle to be drawn
* @param bottom The bottom side of the rectangle to be drawn
* @param paint The paint used to draw the rect
*/
public void drawRect(float left, float top, float right, float bottom, @NonNull Paint paint)
画椭圆:
/**
* 在指定的左边区域内画椭圆
*/
public void drawOval(@NonNull RectF oval, @NonNull Paint paint);
public void drawOval(float left, float top, float right, float bottom, @NonNull Paint paint)
画圆:
/**
* 根据指定的圆心坐标和半径画圆
* @param cx 圆心x坐标
* @param cy 圆心y坐标
* @param radius 圆半径
* @param paint 画笔
*/
public void drawCircle(float cx, float cy, float radius, @NonNull Paint paint)
画圆弧(扇形):
/**
* 根据指定的起始角度在指定的区域内画出指定角度的圆弧或者扇形(如果画笔的mPaint.setStyle(Paint.Style.FILL);则画出来的是扇形,且useCenter为true);以指定的矩形区域中心点为圆心,画内切圆弧。
* @param oval 画圆弧的区域
* @param startAngle 画圆弧的起始角度,钟表3点钟方向为0度,逆时针方向为负值,顺时针方向为正值
* @param sweepAngle 画多少角度的圆弧
* @param useCenter 如果为false:只有一个纯弧线,为true:闭合的边
* @param paint 画笔
*/
public void drawArc(@NonNull RectF oval, float startAngle, float sweepAngle, boolean useCenter,l Paint paint);
/**
*同上
*/
public void drawArc(float left, float top, float right, float bottom, float startAngle,float sweepAngle, boolean useCenter, Paint paint)
如:
RectF r = new RectF(100, 100, 400, 800);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.BLUE);
canvas.drawRect(r, mPaint);
mPaint.setColor(Color.RED);
canvas.drawArc(r, -90, 90f, false, mPaint);//如果指定区域是一个正方形,则画出来的是圆形弧(或圆),如果是长方形,则画出的是椭圆弧(或椭圆)
效果如下:
画内切椭圆:
RectF r = new RectF(100, 100, 400, 800);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.BLUE);
canvas.drawRect(r, mPaint);
mPaint.setColor(Color.RED);
canvas.drawArc(r, 0, 360f, false, mPaint);//在指定的局域r里面,画出一个内切圆
效果图:
画封闭的圆弧:
RectF r = new RectF(100, 100, 400, 800);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.BLUE);
canvas.drawRect(r, mPaint);
mPaint.setColor(Color.RED);
canvas.drawArc(r, -90, 90f, true, mPaint);//画封闭的圆弧
效果如下:
画圆角矩形:
/**
* 画圆角矩形
* @param rect 矩形区域
* @param rx x轴圆角半径
* @param ry y轴圆角半径
* @param paint 画笔
*/
public void drawRoundRect(@NonNull RectF rect, float rx, float ry, @NonNull Paint paint);
public void drawRoundRect(float left, float top, float right, float bottom, float rx, float ry,
@NonNull Paint paint)
画图片:
/*
* @param bitmap 需要绘制的图片
* @param left 开始绘制图片的左上角的x坐标
* @param top 开始绘制图片的左上角的y坐标
* @param paint 画笔
*/
public void drawBitmap(@NonNull Bitmap bitmap, float left, float top, @Nullable Paint paint);
/*
* @param bitmap 绘制的图片
* @param src 见下面解释
* @param dst
* @param paint 画笔
*/
public void drawBitmap(Bitmap bitmap,Rect src,RectF dst,Paint paint);
public void drawBitmap(Bitmap bitmap,Rect src,Rect dst,
@Nullable Paint paint);
/**
* 根据指定的矩阵绘制图片
* @param bitmap 需要绘制的图片
* @param matrix 矩阵
* @param paint 画笔
*/
public void drawBitmap(@NonNull Bitmap bitmap, @NonNull Matrix matrix, @Nullable Paint paint)
该方法有两个功能:
1.只绘制原有bitmap对象的一部分。
2.还可以将要绘制的bitmap缩放到指定的区域。
- 只绘制原有bitmap对象的一部分 :
我们知道Bitmap是一个矩形,其是有宽度和高度的,也就说以bitmap对象本身作为坐标系(原点在bitmap左上角),我们可以构建一个Rect对象,如果满足left为0,top为0,right为bitmap的宽度,bottom为bitmap的高度,那么就说名我们要绘制整个Bitmap。但是有时候我们只想绘制Bitmap的一部分,例如我们上面的图中所示,我们想只绘制Android图像的头部区域怎么办呢?办法是我们构建一个Rect对象,定义我们要绘制Bitmap的哪些部位。 比如我们通过代码srcRect.bottom = (int)(0.33 * bitmap.getHeight())指定了我们只绘制bitmap对象头部1/3的位置,即Android图像的头部,这样我们用该指定的srcRect绘制bitmap时只绘制了其头部位置。需要特别注意的是,srcRect中left、top、right、bottom的值都是以Bitmap本身的局部坐标系为基础的。 - 将要绘制的bitmap缩放到指定的区域 :
有时候我们需要将原有的bitmap进行放大或缩小,如上图所示,我们将原有图片放大了,这怎么做呢?我们需要指定RectF类型的参数dstRectF,以便告诉Android将srcRect中定义的bitmap缩放到哪里。即Android会将srcRect中定义的bitmap缩放到dstRectF区域范围内。需要注意的是,此处的dstRecF是绘图坐标系中的坐标,不是Bitmap本身的局部坐标系。我们在代码中保证了dstRecF的长宽比与srcRect中的长宽比相同,这样不会导致图片长宽比例变形,效果见上图中的第二个放大的图形。
画文字:
/**
* 画文字
* @param text 需要绘制的文字
* @param x 绘制文字起始点x坐标
* @param y 绘制文字的基线(baseline)y坐标
* @param paint 画笔
*/
public void drawText(@NonNull String text, float x, float y, @NonNull Paint paint) ;
/**
* Draw the text, with origin at (x,y), using the specified paint.
* The origin is interpreted based on the Align setting in the paint.
*
* @param text 绘制的文字内容
* @param start 开始脚标
* @param end 结束脚标
* @param x x轴偏移量,即文字开始绘制时的x轴坐标
* @param y baseline的y坐标
* @param paint 画笔
*/
public void drawText(@NonNull String text, int start, int end, float x, float y, Paint paint);
public void drawText(@NonNull char[] text, int index, int count, float x, float y,
@NonNull Paint paint);//同上,只是文字变成了数组
关于baseline的y坐标的计算情参考另外一篇博客:Canvas的drawText方法详解
沿路径画文字:
/**
* 沿路径画文字,如沿着圆圈的外边画一串文字等
* @param text 绘制的文字
* @param path 沿着画文字的路径
* @param hOffset 与路径起始点的水平偏移距离
* @param vOffset 与路径中心的垂直偏移量
* @param paint 画笔
*/
public void drawTextOnPath(char[] text, int index, int count, Path path,float hOffset, float vOffset,Paint paint);
/**
* 同上
*/
public void drawTextOnPath(String text, Path path, float hOffset,float vOffset, @NonNull Paint paint);
实例代码:
Paint paint = new Paint();
Path path = new Path();
path.addCircle(500, 500, 300, Path.Direction.CW);//顺时针方向绘制圆
paint.setStrokeWidth(20);
paint.setColor(Color.BLUE);
paint.setStyle(Paint.Style.STROKE);
canvas.drawPath(path, paint);
paint.reset();
paint.setColor(Color.RED);
paint.setTextSize(40);
canvas.drawTextOnPath("世界和平!!!", path, 0, -10, paint);
实现的效果图:
总结:至此Canvas常用的绘制方法就介绍完了,Canvas中还有其他常用的Api方法,如Canvas的旋转,缩放等,在接下来的博客中,会继续介绍。