27
2017
09

Canvas的基本使用

Canvas直面意思是画布,其实是一个封装了很多绘制方法的工具类。
绘制图像有四大基本的要素:

  1. 一个用来保存像素的Bitmap。
  2. 一个用来执行绘制操作的工具类Canvas。
  3. 绘制的东西,如指明画直线,画文字以及其他各种我们想绘制的东西。
  4. 绘制用的画笔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 绘制文字起始点y坐标 * @param paint 画笔 */
public void drawText(@NonNull String text, float x, float y, @NonNull Paint paint) ;
上一篇:android 工具轮子 下一篇:css 怎么覆盖框架样式