Canvas:画布


* The Canvas class holds the "draw" calls. To draw something, you need
* 4 basic components: A Bitmap to hold the pixels, a Canvas to host
* the draw calls (writing into the bitmap), a drawing primitive (e.g. Rect,
* Path, text, Bitmap), and a paint (to describe the colors and styles for the
* drawing)


译文:

Canvas类保存“draw”调用。要绘制一些东西,您需要4个基本组件:一个用于保存像素的位图、一个用于承载绘制调用(写入位图)的画布、一个绘图原语(例如矩形、路径、文本、位图)和一个油漆(用于描述图纸)

我们常见的理解属于一个画布,只要作画就需要画布,至于在画布上画什么,由参与者自己决定。

图形组合:

任何图形都可以通过点、线、面来完成,如何做到完美的绘画者,我们需要知道Canvas的api都提供了什么,他能干什么

作画需要什么?

1.笔:Paint

2.画布:Canvas

有了笔和画笔,基本可以画很多东西。

Paint

画笔提供了最基础的绘画功能,颜色、画笔大小、样式等。我们只需要简单的设计几个参数就可以使用

  •        setColor(); //设置画笔的颜色
  •   setAntiAlias(); //设置画笔的锯齿效果
  •   setARGB(); //设置画笔的A、R、G、B值
  •   setAlpha(); //设置画笔的Alpha值
  •   setTextSize(); //设置字体的尺寸
  •   setStyle(); //设置画笔的风格(空心或实心)
  •   setStrokeWidth(); //设置空心边框的宽度

有这几种参数,基本就可以完成笔的设置,如果想个性化画笔,可以参考其他Paint的API

Canvas 常用的API的介绍:

1.绘画矩形:drawArc

public void drawArc(@NonNull RectF oval, float startAngle, float sweepAngle, boolean useCenter,         @NonNull Paint paint)

RectF :画布的大小

startAngle: 开始角度,这个值只能决定图形的开始角度,不能改变图的开角角度。

sweepAngle:扫描的角度,正常就是图形的角度

useCenter:是否以中心旋转,如果是,画中的扇形中心在圆中心,否则就是一个普通的扇形

paint:画笔

Android Canvas画布的详解与使用,以及View的绘画(一)_android

1.1拼色扇形

在一些统计图中,我们经常看到百分比的统计图,这是怎么做到的呢?其实这类图做法也是通过绘制图形完成,但是绘制的时候需要注意图层问题。

注意1.Canvas是一层一层绘制的,如果处理多图形拼图,最大层应该在最下方。

Android Canvas画布的详解与使用,以及View的绘画(一)_java_02

RectF rectF = new RectF(0, 0, getMeasuredWidth(), getMeasuredHeight());


        if (paint == null) {
            paint = new Paint();
        }

        paint.setColor(Color.RED);
        paint.setStrokeWidth(2);
        paint.setStyle(Paint.Style.FILL);

        canvas.drawArc(rectF, 0, 360, true, paint);
        canvas.save();
        paint.setColor(Color.YELLOW);
        canvas.drawArc(rectF, 0, 150, true, paint);
        paint.setColor(Color.BLUE);
        canvas.drawArc(rectF, 0, 90, true, paint);

        paint.setColor(Color.GRAY);
        canvas.drawArc(rectF, 0, 30, true, paint);

这里面有四种扇形,红色、黄色、绿色、灰色

灰色开角:30

绿色开角:90

黄色开角:150

红色开角:360(圆形)

视觉上:

灰色:30°

绿色:60°

黄色:60°

红色:210°

技巧:

先算出各个角度,再计算出各个扇形的开角。注意先绘制大图形,再绘制小的,否则360°先绘制会导致图形的遮挡问题

1.2绘制路径:drawPath

public void drawPath(@NonNull Path path, @NonNull Paint paint)

path:路径值,又因为path可以完成各种路径的构建,关于path会单独讲解

正常path绘制很多东西,如果组成一个画面由三个点

paint:画笔

Android Canvas画布的详解与使用,以及View的绘画(一)_开发语言_03

private void drawPath(Canvas canvas) {
        Path path = new Path();
        path.moveTo(100, 100);
        path.lineTo(300, 300);
        path.lineTo(200,300);
        path.close();



        canvas.drawPath(path, paint);

    }

1.3组合绘图,绘制复杂的图形或者需要耗时较长,可以通过该方法:drawPicture

public void drawPicture(@NonNull Picture picture)

picture:图片或者海报

1.4  绘制色块,这个色块类似一个填充色,以ARGB颜色来完成drawARGB

public void drawARGB(int a, int r, int g, int b)

a:透明度

r:红色

g:绿色

b:蓝色

值可以参考色值:0-255,2^8-1

Android Canvas画布的详解与使用,以及View的绘画(一)_位图_04

1.4-1绘制bitmap资源:drawBitmap

public void drawBitmap(@NonNull Bitmap bitmap, float left, float top, @Nullable Paint paint)

bitmap:bitmap资源

left:从布局左边的坐标点,类似View的X轴

top:从布局的顶部的坐标点,类似View的Y轴

paint:画笔

private void drawBitmap(Canvas canvas)
    {
        canvas.drawBitmap(getBitmap(),0,0,paint);
        canvas.save();
    }

Android Canvas画布的详解与使用,以及View的绘画(一)_数组_05

1.4图片扭曲特效:drawBitmapMesh

public void drawBitmapMesh(@NonNull Bitmap bitmap, int meshWidth, int meshHeight,         @NonNull float[] verts, int vertOffset, @Nullable int[] colors, int colorOffset,         @Nullable Paint paint) 

参数:

1.bitmap:指定需要扭曲的源位图。

2.meshwidth:该参数控制在横向上把该源位图划分成多少格。

3.meshheight:该参数控制在纵向上把该源位图划分成多少格。

4.verts:该参数是一个长度为( meshwidth+1)(meshheight+1)2的数组,它记录了扭曲后的位图各“顶点”(网格线的交点)位置。虽然它是个一维数组,实际上它记录的数据是形如(x0,y0)、(x1,y1)、(x2,y2)、(xN,yN)格式的数据,这些数组元素控制对 bitmap位图的扭曲效果。

5.vertOffset:控制verts数组中从第几个数组元素开始才对 bitmap进行扭曲(忽略veroffset之前数据的扭曲效果)。

floa[] verts={(x1,y1)(x2,y2)},扭曲坐标点,奇数是y轴,偶数是x轴

Android Canvas画布的详解与使用,以及View的绘画(一)_开发语言_06

1.5画圆:drawCircle

public void drawCircle(float cx, float cy, float radius, @NonNull Paint paint)

cx:圆心x轴坐标

cy:圆心y轴坐标

radius:半径

paint:画笔


canvas.drawCircle(100,100,100,paint);


Android Canvas画布的详解与使用,以及View的绘画(一)_java_07

1.5划线:drawLine

public void drawLine(float startX, float startY, float stopX, float stopY,      @NonNull Paint paint)


private void drawLine(Canvas canvas) { paint.setStrokeWidth(100); canvas.drawLine(0, 500, 500, 500, paint); }


 startX:起点x坐标

startY:起点y坐标

stopX:终点x坐标

stopY:终点y坐标

paint:画笔

由于线段是两点确定,所以(startX,startY)是起点,(stopX,stopY)是重点

如果想这条线很宽。通过设置画笔的宽度 paint.setStrokeWidth(100);

Android Canvas画布的详解与使用,以及View的绘画(一)_数组_08

1.6画椭圆:drawOval

public void drawOval(@NonNull RectF oval, @NonNull Paint paint)

public void drawOval(float left, float top, float right, float bottom, @NonNull Paint paint)

oval(left,top,right,buttom):椭圆的画布

private void drawOval(Canvas canvas) {
        int width=getMeasuredWidth();
        int height=getMeasuredHeight()/3;

        canvas.drawOval(0,0,width,height,paint);
    }

Android Canvas画布的详解与使用,以及View的绘画(一)_android_09

 1.7绘制画笔:drawPaint


public void drawPaint(@NonNull Paint paint)


paint:这个画笔绘制出来就是当前view的颜色,填充满整个画布

private void drawPaint(Canvas canvas) {
        canvas.drawPaint(paint);
    }

Android Canvas画布的详解与使用,以及View的绘画(一)_位图_10

1.8绘制补丁:drawPatch


public void drawPatch(@NonNull NinePatch patch, @NonNull Rect dst, @Nullable Paint paint)


NinePatch :点九资源

Rect :绘制区域


Bitmap bitmap=getBitmap(); NinePatch patch=new NinePatch(bitmap,bitmap.getNinePatchChunk());


1.9绘制点:drawPoint


public void drawPoint(float x, float y, @NonNull Paint paint)


x:点的x轴坐标

y:点的y轴

点的大小取决于paint的画笔

private void drawPoint(Canvas canvas) {
        paint.setStrokeWidth(20);
        canvas.drawPoint(100, 100, paint);
    }

Android Canvas画布的详解与使用,以及View的绘画(一)_开发语言_11

 1.10绘制文字从点pos出发:drawPosText


public void drawPosText(@NonNull String text, @NonNull @Size(multiple = 2) float[] pos, @NonNull Paint paint)


private void drawPosText(Canvas canvas) {

        float[] pos = new float[]{100, 100};
        canvas.drawPosText("Hellow", pos, paint);

    }

float[] pos:坐标,(x,y)

1.11绘制矩形区域:drawRect


public void drawRect(@NonNull RectF rect, @NonNull Paint paint)


RectF :绘制区域

private void drawRect(Canvas canvas) {
        RectF rectF=new RectF(0,0,500,500);
        canvas.drawRect(rectF,paint);

    }

Android Canvas画布的详解与使用,以及View的绘画(一)_数组_12

1.12绘制色域:drawRGB


public void drawRGB(int r, int g, int b)


public void drawColor(@ColorInt int color) {
    nDrawColor(mNativeCanvasWrapper, color, PorterDuff.Mode.SRC_OVER.nativeInt);
}


一般绘制单个对象,如果不指定区域,默认大小是当前view的宽和高

public void drawRGB(Canvas canvas) {
        canvas.drawRGB(200, 200, 200);
    }

Android Canvas画布的详解与使用,以及View的绘画(一)_数组_13

1.13在矩形内绘制圆角:drawRoundRect


public void drawRoundRect(@NonNull RectF rect, float rx, float ry, @NonNull Paint paint)


RectF :代表绘制区域

rx:圆角在在矩形内的坐标x轴

ry:圆角在在矩形内的坐标y轴

注意:如果rx和ry为0,那么绘制出来的圆角就会0,view就是矩形,如果rx,ry在矩形正中心,那么绘制出来的圆角就是圆形

1.如果x和y都小于矩形的宽和高,那么显示就是矩形四个角被裁剪

2.如果x和y都大于矩形的宽和高,那么显示就是圆

3.如果x和y存在一个小于宽和高,那么显示可能是一个不规则图形

public void drawRoundRect(Canvas canvas)
    {
        RectF rectF=new RectF(0,0,200,200);
        canvas.drawRoundRect(rectF,10,10,paint);
    }

 

Android Canvas画布的详解与使用,以及View的绘画(一)_开发语言_14

Android Canvas画布的详解与使用,以及View的绘画(一)_java_15

Android Canvas画布的详解与使用,以及View的绘画(一)_数组_16

 1.14绘制字符:drawText


public void drawText(@NonNull String text, float x, float y, @NonNull Paint paint)


  绘制的时候,paint style必须设置成paint.setStyle(Paint.Style.FILL);否则会出现一团

private void drawText(Canvas canvas)
    {
        paint.setTextSize(100);
        canvas.drawText("你好",100,100,paint);
    }

text:内容

x:位置的x轴坐标

y:位置的y轴坐标

解释:文字的样式和大小,都是通过paint来设置,关于paint可以自行查看

Android Canvas画布的详解与使用,以及View的绘画(一)_android_17

 1.15绘制文本按路径显示:drawTextOnPath


public void drawTextOnPath(@NonNull String text, @NonNull Path path, float hOffset, float vOffset, @NonNull Paint paint)

* @param text The text to be drawn* @param path The path the text should follow for its baseline
* @param hOffset The distance along the path to add to the text's starting position
* @param vOffset The distance above(-) or below(+) the path to position the text
* @param paint The paint used for the text (e.g. color, size, style)


text :绘制的文本信息

path:路径,最终文本文字会按路径显示

hOffset :沿路径添加到文本起始位置的距离

vOffset :定位文本的路径上方(-)或下方(+)的距离

paint :画笔

private void drawTextOnPath(Canvas canvas) {
        paint.setTextSize(100);
        Path path=new Path();
        path.moveTo(0,500);
        path.lineTo(500,500);
        path.lineTo(500,0);
        path.close();
        canvas.drawTextOnPath("Hello word just do it",path,100,100,paint);
    }

Android Canvas画布的详解与使用,以及View的绘画(一)_android_18

1.16绘制运行中的文本:drawTextRun


public void drawTextRun(@NonNull CharSequence text, int start, int end, int contextStart, int contextEnd, float x, float y, boolean isRtl, @NonNull Paint paint)



* @param text the text to render* @param start the start of the text to render. Data before this position can be used for
*            shaping context.
* @param end the end of the text to render. Data at or after this position can be used for
*            shaping context.
* @param contextStart the index of the start of the shaping context
* @param contextEnd the index of the end of the shaping context
* @param x the x position at which to draw the text
* @param y the y position at which to draw the text
* @param isRtl whether the run is in RTL direction
* @param paint the paint


 text:

start :内容开始索引

end :内容结束的索引

contextStart :塑造语境的起点索引,默认从0开始,

contextEnd 塑造语境的终结索引默认text的长度

isRtl :运行是否在RTL方向

(x ,y):坐标

private void drawTextRun(Canvas canvas)
    {
        paint.setTextSize(100);
        CharSequence text="Hello word just do it";
        canvas.drawTextRun(text,0,text.length(),0,text.length(),100,100,true,paint);

        canvas.drawTextRun(text,0,text.length(),0,text.length(),100,600,false,paint);

    }

Android Canvas画布的详解与使用,以及View的绘画(一)_位图_19

1.17绘制顶点集合,绘制多边形:drawVertices


public void drawVertices(@NonNull VertexMode mode, int vertexCount, @NonNull float[] verts,        int vertOffset, @Nullable float[] texs, int texOffset, @Nullable int[] colors,
        int colorOffset, @Nullable short[] indices, int indexOffset, int indexCount,
        @NonNull Paint paint)



1. mode: 如何解释顶点数组 2. vertexCount:顶点数组中的值数(如果非空,则为相应的texs和颜色数组)。每个逻辑顶点都是两个值(x,y),vertexCount必须是2的倍数 3. verts:网格的顶点数组 4. vertOffset:绘制前要跳过的顶点中的值数 5. texs:可能为空。如果不为空,则指定要采样到当前着色器中的坐标(例如位图平铺或渐变) 6. texOffset:绘制前要跳过的texs中的值数 7. colors:可能为空。如果不为空,则为每个顶点指定一种颜色,以便在三角形上进行插值。8. colorOffset:绘制前要跳过的颜色值的数目 9. indices:如果不为null,则引用到顶点(texs,colors)数组的索引数组 10. indexCount:索引数组中的条目数(如果不为空)。


二、最终总结表如下

 Canvas的经常使用操作

操作类型

相关API

备注

绘制颜色

drawColor, drawRGB, drawARGB

使用单一颜色填充整个画布

绘制基本形状

drawPoint, drawPoints, drawLine, drawLines, drawRect, drawRoundRect, drawOval, drawCircle, drawArc

依次为 点、线、矩形、圆角矩形、椭圆、圆、圆弧

绘制图片

drawBitmap, drawPicture

绘制位图和图片

绘制文本

drawText, drawPosText, drawTextOnPath

依次为 绘制文字、绘制文字时指定每一个文字位置、依据路径绘制文字

绘制路径

drawPath

绘制路径。绘制贝塞尔曲线时也须要用到该函数

顶点操作

drawVertices, drawBitmapMesh

通过对顶点操作能够使图像形变,drawVertices直接对画布作用、 drawBitmapMesh仅仅对绘制的Bitmap作用

画布剪裁

clipPath, clipRect

设置画布的显示区域

画布快照

save, restore, saveLayerXxx, restoreToCount, getSaveCount

依次为 保存当前状态、 回滚到上一次保存的状态、 保存图层状态、 回滚到指定状态、 获取保存次数

画布变换

translate, scale, rotate, skew

依次为 位移、缩放、 旋转、错切

Matrix(矩阵)

getMatrix, setMatrix, concat

实际画布的位移。缩放等操作的都是图像矩阵Matrix,仅仅只是Matrix比較难以理解和使用。故封装了一些经常使用的方法。