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:画笔

1.1拼色扇形

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

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

        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:画笔

    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

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

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轴

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

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

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

1.7绘制画笔:drawPaint

public void drawPaint(@NonNull Paint paint) 

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

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

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

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

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

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

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可以自行查看

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

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

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比較难以理解和使用。故封装了一些经常使用的方法。

Android Canvas画布的详解与使用,以及View的绘画(一)相关推荐

  1. 自定义View之Canvas(画布)的详解

    接下来学习一下自定义View之Canvas(画布)的详解 先来看看Canvas常用方法: 功能分类 Canvas常用方法 备注 绘制颜色 drawARGB 通过设置ARGB值绘制颜色 drawRGB ...

  2. 【Unity3D-UGUI系列】(一)Canvas 画布组件详解

    推荐阅读 CSDN主页 GitHub开源地址 Unity3D插件分享 简书地址 我的个人博客 QQ群:1040082875   大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉 ...

  3. Android涂鸦画板原理详解——从初级到高级(二)

    前言 前面写了<Android涂鸦画板原理详解--从初级到高级(一)>,讲了涂鸦原理初级和中级的应用,现在讲解高级应用.如果没有看过前面一篇文章的同学,建议先去看看哈. 准备 高级涂鸦涉及 ...

  4. Android应用坐标系统全面详解

    Android应用坐标系统全面详解 原文链接:CSDN@工匠若水,http://blog.csdn.net/yanbober/article/details/50419117 1. 背景 去年有很多人 ...

  5. Android多点触控详解

    本文转载自GcsSloop的 安卓自定义View进阶-多点触控详解 的文章 Android 多点触控详解,在前面的几篇文章中我们大致了解了 Android 中的事件处理流程和一些简单的处理方案,本次带 ...

  6. Android 吸入动画效果详解(仿mac退出效果)

    转载自:http://m.blog.csdn.net/blog/leehong2005/9127095 [转]Android 吸入动画效果详解 1,背景 吸入(Inhale)效果,最初我是在iOS上面 ...

  7. java canvas详解_HTML5的canvas绘图技术详解

    原标题:HTML5的canvas绘图技术详解 本篇教程探讨了HTML5的canvas绘图技术详解,希望阅读本篇文章以后大家有所收获,帮助大家HTML5+CSS3从入门到精通 . < canvas ...

  8. Android自定义控件进阶13-MotionEvent详解

    Android MotionEvent 详解,之前用了两篇文章 事件分发机制原理 和 事件分发机制详解 来讲解事件分发,而作为事件分发主角之一的 MotionEvent 并没有过多的说明,本文就带大家 ...

  9. android jar 包 意见反馈功能,android重点jar包详解.docx

    android重点jar包详解 深入理解View(一):从setContentView谈起 我们都知道?MVC,在Android中,这个?V?即指View,那我们今天就来探探View的究竟.在onCr ...

最新文章

  1. Oracle 存储过程定义和优点及与函数区别
  2. 图片上传 fastDFS
  3. (转)Inno Setup入门(六)——在程序目录下创建文件夹
  4. HDU- 2973 YAPTCHA(威尔逊定理)
  5. google compute test Problem 1题
  6. node静态服务器优缺点_使用 Node.js 的优势和劣势都有哪些?
  7. C# 获取Get请求返回
  8. 异构GoldenGate 12c 单向复制配置
  9. python怎么把两个文件合并工具_python开发目录合并小工具 PathMerge
  10. idea将项目打包(jar包/war包)
  11. 基于react做了一个仿qq空间
  12. 【面试招聘】我的秋招记录——(自然语言处理-面经+感悟)
  13. Flex布局应用---导航栏实现
  14. windows2016小文件服务器,Windows Server 2016 搭建 SMB 共享文件
  15. method not allowed 异常处理
  16. matlab绘制法线信息、矢量场
  17. 【编程题】中国象棋路灯
  18. k8s部署nginx
  19. Python二进制数据处理
  20. RaspberryPi树莓派4B安装系统及基础配置

热门文章

  1. docker学习(十二)docker secret 的使用
  2. 蓝牙耳机哪个品牌比较好?盘点四款好用的蓝牙耳机
  3. 毕业论文引用参考文献的脚注方法
  4. scrollTop记录滚动位置
  5. 致丰巢:品牌管理,才是长久之计
  6. 大都会人寿线下培训第三天回顾
  7. 躺平减脂减重法补充篇——无需控制碳水摄入的有效方法,另推一种健康的运动和防止老年慢性病的方式...
  8. 2.2 华为-软件工程师-7.21笔试题
  9. 智汇云校携手院校组织数千学生参加“2020华为中国大学生ICT大赛”
  10. RJ45接头接法(转)