Android中Canvas绘图基础详解(附源码下载)

来源:互联网 发布:吉林大学人工智能专业 编辑:程序博客网 时间:2024/04/29 13:10

目录(?)[+]

Android中,如果我们想绘制复杂的自定义View或游戏,我们就需要熟悉绘图API。Android通过Canvas类暴露了很多drawXXX方法,我们可以通过这些方法绘制各种各样的图形。Canvas绘图有三个基本要素:Canvas、绘图坐标系以及Paint。Canvas是画布,我们通过Canvas的各种drawXXX方法将图形绘制到Canvas上面,在drawXXX方法中我们需要传入要绘制的图形的坐标形状,还要传入一个画笔Paint。drawXXX方法以及传入其中的坐标决定了要绘制的图形的形状,比如drawCircle方法,用来绘制圆形,需要我们传入圆心的x和y坐标,以及圆的半径。drawXXX方法中传入的画笔Paint决定了绘制的图形的一些外观,比如是绘制的图形的颜色,再比如是绘制圆面还是圆的轮廓线等。Android系统的设计吸收了很多已有系统的诸多优秀之处,比如Canvas绘图。Canvas不是Android所特有的,Flex和Silverlight都支持Canvas绘图,Canvas也是HTML5标准中的一部分,主流的现代浏览器都支持用JavaScript在Canvas上绘图,如果你用过HTML5中的Canvas,你会发现Android的Canvas的绘图API与其很相似。总之,Canvas绘图不是Android所特有的。

为了演示Android中各种drawXXX方法的时候,我做了一个App,通过单击相应的按钮绘制相应的图形,主界面如下所示: 
这里写图片描述


Canvas坐标系与绘图坐标系

Canvas绘图中牵扯到两种坐标系:Canvas坐标系与绘图坐标系。

  • Canvas坐标系 
    Canvas坐标系指的是Canvas本身的坐标系,Canvas坐标系有且只有一个,且是唯一不变的,其坐标原点在View的左上角,从坐标原点向右为x轴的正半轴,从坐标原点向下为y轴的正半轴。

  • 绘图坐标系 
    Canvas的drawXXX方法中传入的各种坐标指的都是绘图坐标系中的坐标,而非Canvas坐标系中的坐标。默认情况下,绘图坐标系与Canvas坐标系完全重合,即初始状况下,绘图坐标系的坐标原点也在View的左上角,从原点向右为x轴正半轴,从原点向下为y轴正半轴。但不同于Canvas坐标系,绘图坐标系并不是一成不变的,可以通过调用Canvas的translate方法平移坐标系,可以通过Canvas的rotate方法旋转坐标系,还可以通过Canvas的scale方法缩放坐标系,而且需要注意的是,translate、rotate、scale的操作都是基于当前绘图坐标系的,而不是基于Canvas坐标系,一旦通过以上方法对坐标系进行了操作之后,当前绘图坐标系就变化了,以后绘图都是基于更新的绘图坐标系了。也就是说,真正对我们绘图有用的是绘图坐标系而非Canvas坐标系。

为了更好的理解绘图坐标系,请看如下的代码:

<code class="hljs mel has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//绘制坐标系</span>    private void drawAxis(Canvas <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>){        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> canvasWidth = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.getWidth();        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> canvasHeight = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.getHeight();        paint.setStyle(Paint.Style.STROKE);        paint.setStrokeCap(Paint.Cap.ROUND);        paint.setStrokeWidth(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6</span> * density);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//用绿色画x轴,用蓝色画y轴</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//第一次绘制坐标轴</span>        paint.setColor(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0xff00ff00</span>);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//绿色</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.drawLine(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, canvasWidth, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, paint);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//绘制x轴</span>        paint.setColor(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0xff0000ff</span>);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//蓝色</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.drawLine(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, canvasHeight, paint);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//绘制y轴</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//对坐标系平移后,第二次绘制坐标轴</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.translate(canvasWidth / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span>, canvasWidth /<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span>);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//把坐标系向右下角平移</span>        paint.setColor(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0xff00ff00</span>);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//绿色</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.drawLine(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, canvasWidth, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, paint);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//绘制x轴</span>        paint.setColor(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0xff0000ff</span>);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//蓝色</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.drawLine(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, canvasHeight, paint);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//绘制y轴</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//再次平移坐标系并在此基础上旋转坐标系,第三次绘制坐标轴</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.translate(canvasWidth / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span>, canvasWidth / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span>);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//在上次平移的基础上再把坐标系向右下角平移</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">rotate</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">30</span>);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//基于当前绘图坐标系的原点旋转坐标系</span>        paint.setColor(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0xff00ff00</span>);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//绿色</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.drawLine(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, canvasWidth, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, paint);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//绘制x轴</span>        paint.setColor(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0xff0000ff</span>);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//蓝色</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.drawLine(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, canvasHeight, paint);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//绘制y轴</span>    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li></ul>

界面如下所示: 
这里写图片描述

第一次绘制绘图坐标系时,绘图坐标系默认情况下和Canvas坐标系重合,所以绘制出的坐标系紧贴View的上侧和左侧; 
第二次首先将坐标轴向右下角平移了一段距离,然后绘制出的坐标系也就整体向右下角平移了; 
第三次再次向右下角平移,并旋转了30度,图上倾斜的坐标系即最后的绘图坐标系。


drawARGB

Canvas中的drawARGB可以用来对整个Canvas以某种统一的颜色整体绘制,四个参数分别是Alpha、Red、Green、Blue,取值都是0-255。 
使用代码如下:

<code class="hljs cs has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">drawARGB</span>(Canvas canvas){        canvas.drawARGB(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">255</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">139</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">197</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">186</span>);    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>

界面如下所示: 
这里写图片描述


drawText

Canvas中用drawText方法绘制文字,代码如下所示:

<code class="hljs mel has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">private void drawText(Canvas <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>){        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> canvasWidth = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.getWidth();        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> halfCanvasWidth = canvasWidth / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> translateY = textHeight;        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//绘制正常文本</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.save();        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.translate(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, translateY);        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.drawText(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"正常绘制文本"</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, paint);        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.restore();        translateY += textHeight * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>;        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//绘制绿色文本</span>        paint.setColor(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0xff00ff00</span>);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置字体为绿色</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.save();        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.translate(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, translateY);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//将画笔向下移动</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.drawText(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"绘制绿色文本"</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, paint);        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.restore();        paint.setColor(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0xff000000</span>);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//重新设置为黑色</span>        translateY += textHeight * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>;        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置左对齐</span>        paint.setTextAlign(Paint.Align.LEFT);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置左对齐</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.save();        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.translate(halfCanvasWidth, translateY);        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.drawText(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"左对齐文本"</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, paint);        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.restore();        translateY += textHeight * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>;        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置居中对齐</span>        paint.setTextAlign(Paint.Align.CENTER);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置居中对齐</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.save();        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.translate(halfCanvasWidth, translateY);        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.drawText(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"居中对齐文本"</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, paint);        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.restore();        translateY += textHeight * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>;        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置右对齐</span>        paint.setTextAlign(Paint.Align.RIGHT);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置右对齐</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.save();        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.translate(halfCanvasWidth, translateY);        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.drawText(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"右对齐文本"</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, paint);        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.restore();        paint.setTextAlign(Paint.Align.LEFT);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//重新设置为左对齐</span>        translateY += textHeight * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>;        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置下划线</span>        paint.setUnderlineText(true);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置具有下划线</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.save();        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.translate(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, translateY);        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.drawText(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"下划线文本"</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, paint);        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.restore();        paint.setUnderlineText(false);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//重新设置为没有下划线</span>        translateY += textHeight * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>;        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//绘制加粗文字</span>        paint.setFakeBoldText(true);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//将画笔设置为粗体</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.save();        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.translate(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, translateY);        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.drawText(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"粗体文本"</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, paint);        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.restore();        paint.setFakeBoldText(false);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//重新将画笔设置为非粗体状态</span>        translateY += textHeight * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>;        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//文本绕绘制起点顺时针旋转</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.save();        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.translate(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, translateY);        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">rotate</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">20</span>);        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.drawText(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"文本绕绘制起点旋转20度"</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, paint);        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.restore();    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li></ul>

界面如下所示: 
这里写图片描述

对以上代码进行一下说明:

  1. Android中的画笔有两种Paint和TextPaint,我们可以Paint来画其他的图形:点、线、矩形、椭圆等。TextPaint继承自Paint,是专门用来画文本的,由于TextPaint继承自Paint,所以也可以用TextPaint画点、线、面、矩形、椭圆等图形。

  2. 我们在上面的代码中将canvas.translate()和canvas.rotate()放到了canvas.save()和canvas.restore()之间,这样做的好处是,在canvas.save()调用时,将当前坐标系保存下来,将当前坐标系的矩阵Matrix入栈保存,然后通过translate或rotate等对坐标系进行变换,然后进行绘图,绘图完成后,我们通过调用canvas.restore()将之前保存的Matrix出栈,这样就将当前绘图坐标系恢复到了canvas.save()执行的时候状态。如果熟悉OpenGL开发,对这种模式应该很了解。

  3. 通过调用paint.setColor(0xff00ff00)将画笔设置为绿色,paint的setColor方法需要传入一个int值,通常情况下我们写成16进制0x的形式,第一个字节存储Alpha通道,第二个字节存储Red通道,第三个字节存储Green通道,第四个字节存储Blue通道,每个字节的取值都是从00到ff。如果对这种设置颜色的方式不熟悉,也可以调用paint.setARGB(int a, int r, int g, int b)方法设置画笔的颜色,不过paint.setColor(int color)的方式更简洁。

  4. 通过调用paint.setTextAlign()设置文本的对齐方式,该对齐方式是相对于绘制文本时的画笔的坐标来说的,在本例中,我们绘制文本时画笔在Canvas宽度的中间。在drawText()方法执行时,需要传入一个x和y坐标,假设该点为P点,P点表示我们从P点绘制文本。当对齐方式为Paint.Align.LEFT时,绘制的文本以P点为基准向左对齐,这是默认的对齐方式;当对齐方式为Paint.Align.CENTER时,绘制的文本以P点为基准居中对齐;当对齐方式为Paint.Align.RIGHT时,绘制的文本以P点为基准向右对齐。

  5. 通过调用paint.setUnderlineText(true)绘制带有下划线的文本。

  6. 通过调用paint.setFakeBoldText(true)绘制粗体文本。

  7. 通过rotate旋转坐标系,我们可以绘制倾斜文本。


drawPoint

Canvas中用drawPoint方法绘制点,代码如下所示:

<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">private void drawPoint(Canvas canvas){        int canvasWidth = canvas<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getWidth</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>        int canvasHeight = canvas<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getHeight</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>        int <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">x</span> = canvasWidth / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>        int deltaY = canvasHeight / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>        int <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">y</span> = deltaY / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>        paint<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setColor</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0xff8bc5ba</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;//设置颜色</span>        paint<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setStrokeWidth</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">50</span> * density)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;//设置线宽,如果不设置线宽,无法绘制点</span>        //绘制Cap为BUTT的点        paint<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setStrokeCap</span>(Paint<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.Cap</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.BUTT</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>        canvas<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.drawPoint</span>(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">x</span>, <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">y</span>, paint)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>        //绘制Cap为ROUND的点        canvas<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.translate</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, deltaY)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>        paint<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setStrokeCap</span>(Paint<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.Cap</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.ROUND</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>        canvas<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.drawPoint</span>(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">x</span>, <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">y</span>, paint)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>        //绘制Cap为SQUARE的点        canvas<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.translate</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, deltaY)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>        paint<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setStrokeCap</span>(Paint<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.Cap</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.SQUARE</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>        canvas<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.drawPoint</span>(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">x</span>, <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">y</span>, paint)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li></ul>

界面如下所示: 
这里写图片描述

下面对以上代码进行说明:

  1. Paint的setStrokeWidth方法可以控制所画线的宽度,通过Paint的getStrokeWidth方法可以得到所画线的宽度,默认情况下,线宽是0。其实strokeWidth不仅对画线有影响,对画点也有影响,由于默认的线宽是0,所以默认情况下调用drawPoint方法无法在Canvas上画出点,为了让大家清楚地看到所画的点,我用Paint的setStrokeWidth设置了一个比较大的线宽,这样我们看到的点也就比较大。

  2. Paint有个setStrokeCap方法可以设置所画线段的时候两个端点的形状,即所画线段的帽端的形状,在下面讲到drawLine方法时会详细说明,其实setStrokeCap方法也会影响所画点的形状。Paint的setStrokeCap方法可以有三个取值:Paint.Cap.BUTT、Paint.Cap.ROUND和Paint.Cap.SQUARE。

  3. 默认情况下Paint的getStrokeCap的返回值是Paint.Cap.BUTT,默认画出来的点就是一个正方形,上图第一个点即是用BUTT作为帽端画的。

  4. 我们可以调用setStrokeCap方法设置Paint的strokeCap为Paint.Cap.ROUND时,画笔画出来的点就是一个圆形,上图第二个点即是用ROUND作为帽端画的。

  5. 调用调用setStrokeCap方法设置Paint的strokeCap为Paint.Cap.SQUARE时,画笔画出来的电也是一个正方形,与用BUTT画出来的效果在外观上相同,上图最后一个点即时用SQUARE作为帽端画的。


drawLine

Canvas通过drawLine方法绘制一条线段,通过drawLines方法绘制多段线,使用代码如下所示: 
这里写图片描述

下面对以上代码进行说明:

  1. drawLine方法接收四个数值,即起点的x和y以及终点的x和y,绘制一条线段。

  2. drawLines方法接收一个float数组pts,需要注意的是在用drawLines绘图时,其每次从pts数组中取出四个点绘制一条线段,然后再取出后面四个点绘制一条线段,所以要求pts的长度需要是4的倍数。假设我们有四个点,分别是p1、p2、p3、p4,我们依次将其坐标放到pts数组中,即pts = {p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y},那么用drawLines绘制pts时,你会发现p1和p2之间画了一条线段,p3和p4之间画了一条线段,但是p2和p3之间没有画线段,这样大家就应该能明白drawLines每次都需要从pts数组中取出4个值绘制一条线段的意思了。

  3. 通过调用Paint的setStrokeWidth方法设置线的宽度。

  4. 上面在讲drawPoint时提到了strokeCap对所绘制点的形状的影响,通过drawLine绘制的线段也受其影响,体现在绘制的线段的两个端点的形状上。

    • Paint.Cap.BUTT 
      当用BUTT作为帽端时,所绘制的线段恰好在起点终点位置处戛然而止,两端是方形,上图中第一条加粗的线段就是用BUTT作为帽端绘制的。

    • Paint.Cap.ROUND 
      当用ROUND作为帽端时,所绘制的线段的两端端点会超出起点和终点一点距离,并且两端是圆形状,上图中第二条加粗的线段就是用ROUND作为帽端绘制的。

    • Paint.Cap.SQUARE 
      当用SQUARE作为帽端时,所绘制的线段的两端端点也会超出起点和终点一点距离,两端点的形状是方形,上图中最后一条加粗的线段就是用SQUARE作为帽端绘制的。


drawRect

Canvas通过drawRect方法绘制矩形,使用代码如下所示:

<code class="hljs mel has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">private void drawRect(Canvas <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>){        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> canvasWidth = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.getWidth();        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> canvasHeight = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.getHeight();        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//默认画笔的填充色是黑色</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> left1 = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> top1 = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> right1 = canvasWidth / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> bottom1 = canvasHeight /<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.drawRect(left1, top1, right1, bottom1, paint);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//修改画笔颜色</span>        paint.setColor(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0xff8bc5ba</span>);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//A:ff,R:8b,G:c5,B:ba</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> left2 = canvasWidth / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span> * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> top2 = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> right2 = canvasWidth - <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> bottom2 = canvasHeight / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.drawRect(left2, top2, right2, bottom2, paint);    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li></ul>

界面如下所示: 
这里写图片描述

其方法签名是drawRect(float left, float top, float right, float bottom, Paint paint),left和right表示矩形的左边和右边分别到绘图坐标系y轴正半轴的距离,top和bottom表示矩形的上边和下边分别到绘图坐标系x轴正半轴的距离。


drawCircle

Canvas中用drawCircle方法绘制圆形,使用代码如下所示:

<code class="hljs mel has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">private void drawCircle(Canvas <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>){        paint.setColor(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0xff8bc5ba</span>);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置颜色</span>        paint.setStyle(Paint.Style.FILL);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//默认绘图为填充模式</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> canvasWidth = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.getWidth();        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> canvasHeight = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.getHeight();        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> halfCanvasWidth = canvasWidth / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> count = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> D = canvasHeight / (count + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> R = D / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>;        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//绘制圆</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.translate(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, D / (count + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>));        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.drawCircle(halfCanvasWidth, R, R, paint);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//通过绘制两个圆形成圆环</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//1. 首先绘制大圆</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.translate(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, D + D / (count + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>));        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.drawCircle(halfCanvasWidth, R, R, paint);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//2. 然后绘制小圆,让小圆覆盖大圆,形成圆环效果</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> r = (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>)(R * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0.75</span>);        paint.setColor(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0xffffffff</span>);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//将画笔设置为白色,画小圆</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.drawCircle(halfCanvasWidth, R, r, paint);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//通过线条绘图模式绘制圆环</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.translate(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, D + D / (count + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>));        paint.setColor(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0xff8bc5ba</span>);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置颜色</span>        paint.setStyle(Paint.Style.STROKE);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//绘图为线条模式</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> strokeWidth = (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span>)(R * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0.25</span>);        paint.setStrokeWidth(strokeWidth);        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.drawCircle(halfCanvasWidth, R, R, paint);    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li></ul>

界面如下所示: 
这里写图片描述

下面对以上代码进行说明:

  1. 其方法签名是drawCircle (float cx, float cy, float radius, Paint paint),在使用时需要传入圆心的坐标以及半径,当然还有画笔Paint对象。

  2. 当我们在调用drawCircle、drawOval、drawArc、drawRect等方法时,我们既可以绘制对应图形的填充面,也可以只绘制该图形的轮廓线,控制的关键在于画笔Paint中的style。Paint通过setStyle方法设置要绘制的类型,style有取三种值:Paint.Style.FILL、Paint.Style.STROKE和Paint.Style.FILL_AND_STROKE。

    • 当style为FILL时,绘制是填充面,FILL是Paint默认的style;
    • 当style为STROKE时,绘制的是图形的轮廓线;
    • 当style为FILL_AND_STROKE时,同时绘制填充面和轮廓线,不过这种情况用的不多,因为填充面和轮廓线是用同一种颜色绘制的,区分不出轮廓线的效果。
  3. 在Paint的style是FILL时,我们通过drawCircle绘制出圆面,如上图中的第一个图形所示。

  4. 我们可以通过绘制两个圆面的方式绘制出圆环的效果。首先将画笔设置为某一颜色,且style设置为FILL状态,通过drawCircle绘制一个大的圆面;然后将画笔Paint的颜色改为白色或其他颜色,并减小半径再次通过drawCircle绘制一个小圆,这样就用小圆遮盖了大圆的一部分,未遮盖的部分便自然形成了圆环的效果,如上图中的第二个图形所示。

  5. 除了上述方法,我们还有一种办法绘制圆环的效果。我们首先将画笔Paint的style设置为STROKE模式,表示画笔处于画线条模式,而非填充模式。然后为了让圆环比较明显有一定的宽度,我们需要调用Paint的setStrokeWidth方法设置线宽。最后调用drawCircle方法绘制出宽度比较大的圆的轮廓线,也就形成了圆环效果,如上图中的最后一个图形所示。此处需要说明的是,当我们用STROKE模式画圆时,轮廓线是以实际圆的边界为分界线分别向内向外扩充1/2的线宽的距离,比如圆的半径是100,线宽是20,那么在STROKE模式下绘制出的圆环效果相当于半径为110的大圆和半径为90的小圆形成的效果,100 + 20 / 2 = 110, 100 - 20/2 = 90。


drawOval

Canvas中提供了drawOval方法绘制椭圆,其使用代码如下所示:

<code class="hljs mel has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">private void drawOval(Canvas <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>){        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> canvasWidth = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.getWidth();        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> canvasHeight = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.getHeight();        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> quarter = canvasHeight / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span>;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> left = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span> * density;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> top = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> right = canvasWidth - left;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> bottom= quarter;        RectF rectF = new RectF(left, top, right, bottom);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//绘制椭圆形轮廓线</span>        paint.setStyle(Paint.Style.STROKE);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置画笔为画线条模式</span>        paint.setStrokeWidth(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> * density);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置线宽</span>        paint.setColor(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0xff8bc5ba</span>);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置线条颜色</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.translate(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, quarter / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span>);        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.drawOval(rectF, paint);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//绘制椭圆形填充面</span>        paint.setStyle(Paint.Style.FILL);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置画笔为填充模式</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.translate(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, (quarter + quarter / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span>));        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.drawOval(rectF, paint);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//画两个椭圆,形成轮廓线和填充色不同的效果</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.translate(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, (quarter + quarter / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span>));        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//1. 首先绘制填充色</span>        paint.setStyle(Paint.Style.FILL);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置画笔为填充模式</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.drawOval(rectF, paint);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//绘制椭圆形的填充效果</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//2. 将线条颜色设置为蓝色,绘制轮廓线</span>        paint.setStyle(Paint.Style.STROKE);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置画笔为线条模式</span>        paint.setColor(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0xff0000ff</span>);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置填充色为蓝色</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.drawOval(rectF, paint);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置椭圆的轮廓线</span>    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li></ul>

其界面如下所示: 
这里写图片描述

下面对以上代码进行说明:

  1. 其方法签名是public void drawOval (RectF oval, Paint paint),RectF有四个字段,分别是left、top、right、bottom, 
    这四个值对应了椭圆的左、上、右、下四个点到相应坐标轴的距离,具体来说,left和right表示椭圆的最左侧的点和最右侧的点到绘图坐标系的y轴的距离,top和bottom表示椭圆的最顶部的点和最底部的点到绘图坐标系的x轴的距离,这四个值就决定了椭圆的形状,right与left的差值即为椭圆的长轴,bottom与top的差值即为椭圆的短轴,如下图所示: 
    这里写图片描述

  2. 通过Paint的setStyle方法将画笔的style设置成STROKE,即画线条模式,这种情况下,用画笔画出来的是椭圆的轮廓线,而非填充面,如上图中的第一个图形所示。

  3. 当将画笔Paint的style设置为FILL时,即填充模式,这种情况下,用画笔画出来的是椭圆的填充面,如上图中的第二个图形所示。

  4. 如果我们想绘制带有其他颜色轮廓线的椭圆面,我们需要绘制两个椭圆。首先以FILL模式画一个椭圆的填充面,然后更改画笔颜色,以STROKE模式画椭圆的轮廓线,如上图中的最后一个图形所示。这样从外观上看,好像是椭圆面与椭圆的轮廓线颜色不同。


drawArc

Canvas中提供了drawArc方法用于绘制弧,这里的弧指两种:弧面和弧线,弧面即用弧围成的填充面,弧线即为弧面的轮廓线。其使用代码如下所示:

<code class="hljs mel has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">private void drawArc(Canvas <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>){        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> canvasWidth = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.getWidth();        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> canvasHeight = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.getHeight();        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> count = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> ovalHeight = canvasHeight / (count + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> left = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span> * density;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> top = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> right = canvasWidth - left;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> bottom= ovalHeight;        RectF rectF = new RectF(left, top, right, bottom);        paint.setStrokeWidth(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> * density);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置线宽</span>        paint.setColor(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0xff8bc5ba</span>);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置颜色</span>        paint.setStyle(Paint.Style.FILL);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//默认设置画笔为填充模式</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//绘制用drawArc绘制完整的椭圆</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.translate(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, ovalHeight / count);        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.drawArc(rectF, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">360</span>, true, paint);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//绘制椭圆的四分之一,起点是钟表的3点位置,从3点绘制到6点的位置</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.translate(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, (ovalHeight + ovalHeight / count));        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.drawArc(rectF, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">90</span>, true, paint);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//绘制椭圆的四分之一,将useCenter设置为false</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.translate(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, (ovalHeight + ovalHeight / count));        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.drawArc(rectF, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">90</span>, false, paint);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//绘制椭圆的四分之一,只绘制轮廓线</span>        paint.setStyle(Paint.Style.STROKE);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置画笔为线条模式</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.translate(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, (ovalHeight + ovalHeight / count));        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.drawArc(rectF, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">90</span>, true, paint);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//绘制带有轮廓线的椭圆的四分之一</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//1. 先绘制椭圆的填充部分</span>        paint.setStyle(Paint.Style.FILL);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置画笔为填充模式</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.translate(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, (ovalHeight + ovalHeight / count));        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.drawArc(rectF, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">90</span>, true, paint);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//2. 再绘制椭圆的轮廓线部分</span>        paint.setStyle(Paint.Style.STROKE);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置画笔为线条模式</span>        paint.setColor(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0xff0000ff</span>);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置轮廓线条为蓝色</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">canvas</span>.drawArc(rectF, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">90</span>, true, paint);    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li></ul>

界面如下所示: 
这里写图片描述

下面对以上代码进行说明:

  1. 用drawArc画的弧指的是椭圆弧,即椭圆的一部分。当然,如果椭圆的长轴和和短轴相等,这时候我们就可以用drawArc方法绘制圆弧。其方法签名是:

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

    • oval是RecF类型的对象,其定义了椭圆的形状。
    • startAngle指的是绘制的起始角度,钟表的3点位置对应着0度,如果传入的startAngle小于0或者大于等于360,那么用startAngle对360进行取模后作为起始绘制角度。
    • sweepAngle指的是从startAngle开始沿着钟表的顺时针方向旋转扫过的角度。如果sweepAngle大于等于360,那么会绘制完整的椭圆弧。如果sweepAngle小于0,那么会用sweepAngle对360进行取模后作为扫过的角度。
    • useCenter是个boolean值,如果为true,表示在绘制完弧之后,用椭圆的中心点连接弧上的起点和终点以闭合弧;如果值为false,表示在绘制完弧之后,弧的起点和终点直接连接,不经过椭圆的中心点。
  2. 在代码中我们一开始设置的Paint的style为FILL,即填充模式。通过上面的描述我们知道,drawOval方法可以看做是drawArc方法的一种特例。如果在drawArc方法中sweepAngle为360,无论startAngle为多少,drawArc都会绘制一个椭圆,如上图中第一个图形,我们用canvas.drawArc(rectF, 0, 360, true, paint)绘制了一个完整的椭圆,就像用drawOval画出的那样。

  3. 当我们调用方法canvas.drawArc(rectF, 0, 90, true, paint)时, 我们指定了起始角度为0,然后顺时针绘制90度,即我们会绘制从3点到6点这90度的弧,如上图中第二个图形所示,我们绘制了一个椭圆的右下角的四分之一的弧面,需要注意的是我们此处设置的useCenter为true,所以弧上的起点(3点位置)和终点(6点位置)都和椭圆的中心连接了形成了。

  4. 当我们调用方法canvas.drawArc(rectF, 0, 90, false, paint)时,我们还是绘制椭圆右下角的弧面,不过这次我们将useCenter设置成了false,如上图中的第三个图形所示,弧上的起点(3点位置)和终点(6点位置)直接相连闭合了,而没有经过椭圆的中心点。

  5. 上面介绍到的绘图都是在画笔Paint处于FILL状态下绘制的。我们可以通过paint.setStyle(Paint.Style.STROKE)方法将画笔的style改为STROKE,即绘制线条模式。然后我们再次执行canvas.drawArc(rectF, 0, 90, true, paint),初始角度为0,扫过90度的区域,useCenter为true,绘制的效果见上图中第四个图形,此时我们只绘制了椭圆的轮廓线。需要注意的,由于Paint默认的线宽为0,所以在绘制之前要确保掉用过Paint.setStrokeWidth()方法以设置画笔的线宽。

  6. 如果我们想绘制出带有其他颜色轮廓线的弧面时,该怎么办呢?我们可以分两步完成:首先,将画笔Paint的style设置为FILL模式,通过drawArc方法绘制出弧面。然后,将画笔Paint的style设置为STROKE模式,并通过paint的setColor()方法改变画笔的颜色,最后drawArc方法绘制出弧线。这样我们就能绘制出带有其他颜色轮廓线的弧面了,如上图中最后一个图形所示。


drawPath

Canvas通过drawPath方法可以绘制Path。那Path是什么呢?Path致以过来是路径的意思,在Android中,Path是一种线条的组合图形,其可以由直线、二次曲线、三次曲线、椭圆的弧等组成。Path既可以画线条,也可以画填充面。其使用代码如下所示:

<code class="hljs cpp has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> drawPath(Canvas canvas){        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> canvasWidth = canvas.getWidth();        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> deltaX = canvasWidth / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span>;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> deltaY = (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>)(deltaX * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0.75</span>);        paint.setColor(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0xff8bc5ba</span>);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置画笔颜色</span>        paint.setStrokeWidth(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span>);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置线宽</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/*--------------------------用Path画填充面-----------------------------*/</span>        paint.setStyle(Paint.Style.FILL);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置画笔为填充模式</span>        Path path = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Path();        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//向Path中加入Arc</span>        RectF arcRecF = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> RectF(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, deltaX, deltaY);        path.addArc(arcRecF, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">135</span>);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//向Path中加入Oval</span>        RectF ovalRecF = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> RectF(deltaX, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, deltaX * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, deltaY);        path.addOval(ovalRecF, Path.Direction.CCW);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//向Path中添加Circle</span>        path.addCircle((<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span>)(deltaX * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2.5</span>), deltaY / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, deltaY / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, Path.Direction.CCW);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//向Path中添加Rect</span>        RectF rectF = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> RectF(deltaX * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, deltaX * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span>, deltaY);        path.addRect(rectF, Path.Direction.CCW);        canvas.drawPath(path, paint);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/*--------------------------用Path画线--------------------------------*/</span>        paint.setStyle(Paint.Style.STROKE);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置画笔为线条模式</span>        canvas.translate(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, deltaY * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>);        Path path2 = path;        canvas.drawPath(path2, paint);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/*-----------------使用lineTo、arcTo、quadTo、cubicTo画线--------------*/</span>        paint.setStyle(Paint.Style.STROKE);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置画笔为线条模式</span>        canvas.translate(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, deltaY * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>);        Path path3 = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Path();        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//用pointList记录不同的path的各处的连接点</span>        List<Point> pointList = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ArrayList<Point>();        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//1. 第一部分,绘制线段</span>        path3.moveTo(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>);        path3.lineTo(deltaX / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//绘制线段</span>        pointList.add(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Point(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>));        pointList.add(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Point(deltaX / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>));        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//2. 第二部分,绘制椭圆右上角的四分之一的弧线</span>        RectF arcRecF1 = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> RectF(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, deltaX, deltaY);        path3.arcTo(arcRecF1, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">270</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">90</span>);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//绘制圆弧</span>        pointList.add(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Point(deltaX, deltaY / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>));        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//3. 第三部分,绘制椭圆左下角的四分之一的弧线</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//注意,我们此处调用了path的moveTo方法,将画笔的移动到我们下一处要绘制arc的起点上</span>        path3.moveTo(deltaX * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1.5f</span>, deltaY);        RectF arcRecF2 = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> RectF(deltaX, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, deltaX * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, deltaY);        path3.arcTo(arcRecF2, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">90</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">90</span>);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//绘制圆弧</span>        pointList.add(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Point((<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>)(deltaX * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1.5</span>), deltaY));        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//4. 第四部分,绘制二阶贝塞尔曲线</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//二阶贝塞尔曲线的起点就是当前画笔的位置,然后需要添加一个控制点,以及一个终点</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//再次通过调用path的moveTo方法,移动画笔</span>        path3.moveTo(deltaX * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1.5f</span>, deltaY);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//绘制二阶贝塞尔曲线</span>        path3.quadTo(deltaX * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, deltaX * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2.5f</span>, deltaY / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>);        pointList.add(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Point((<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>)(deltaX * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2.5</span>), deltaY / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>));        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//5. 第五部分,绘制三阶贝塞尔曲线,三阶贝塞尔曲线的起点也是当前画笔的位置</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//其需要两个控制点,即比二阶贝赛尔曲线多一个控制点,最后也需要一个终点</span>        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//再次通过调用path的moveTo方法,移动画笔</span>        path3.moveTo(deltaX * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2.5f</span>, deltaY / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//绘制三阶贝塞尔曲线</span>        path3.cubicTo(deltaX * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, deltaX * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3.5f</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, deltaX * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span>, deltaY);        pointList.add(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Point(deltaX * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span>, deltaY));        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//Path准备就绪后,真正将Path绘制到Canvas上</span>        canvas.drawPath(path3, paint);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//最后绘制Path的连接点,方便我们大家对比观察</span>        paint.setStrokeWidth(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//将点的strokeWidth要设置的比画path时要大</span>        paint.setStrokeCap(Paint.Cap.ROUND);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//将点设置为圆点状</span>        paint.setColor(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0xff0000ff</span>);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置圆点为蓝色</span>        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(Point p : pointList){            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//遍历pointList,绘制连接点</span>            canvas.drawPoint(p.x, p.y, paint);        }    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li></ul>

界面如下所示: 
这里写图片描述

下面对以上代码进行说明:

  1. Canvas的drawPath()方法接收Path和Paint两个参数。当Paint的style是FILL时,我们可以用darwPath来画填充面。Path类提供了addArc、addOval、addCircle、addRect等方法,可以通过这些方法可以向Path添加各种闭合图形,Path甚至还提供了addPath方法让我们将一个Path对象添加到另一个Path对象中作为其一部分。当我们通过Path的addXXX方法向Path中添加了各种图形后,我们就可以调用canvas.drawPath(path, paint)绘制出Path了,如上图中第一行中的几个图形所示。

  2. 我们可以通过调用Paint的setStyle()方法将画笔Paint设置为STROKE,即线条模式, 然后我们再次执行canvas.darwPath()方法绘制同一个Path对象,我们这次绘制的就只是Path的轮廓线了,如上图中第二行中的几个图形所示。

  3. Path对象还有很多xxTo方法,比如lineTo、arcTo、quadTo、cubicTo等,通过这些方法,我们可以方便的从画笔位置绘制到指定坐标的连续线条,如上图中最后一行的几个线状图形所示。我们用了lineTo、arcTo、quadTo、cubicTo这四种方法画了五段线条,下面会解释,并且单独通过调用drawPoint画出了每段线条的两个端点,方便大家观察。

    • moveTo方法用于设置下一个线条的起始点,可以认为是移动了画笔,但说移动画笔不严格,后面会解释,此处大家暂且这么理解。

    • lineTo的方法签名是public void lineTo (float x, float y),Path的lineTo方法会从当前画笔的位置到我们指定的坐标构建一条线段,然后将其添加到Path对象中,如上图中最后一行图形中的第一条线段所示。

    • arcTo的方法签名是public void arcTo (RectF oval, float startAngle, float sweepAngle),oval、startAngle与sweepAngle的参数与之前提到的darwArc方法对应的形参意义相同,在此不再赘述。Path的arcTo方法会构建一条弧线并添加到Path对象中,如上图中最后一行图形中的第二条和第三条线状图形所示,这两条弧线都是通过Path的arcTo方法添加的。

    • quadTo是用来画二阶贝塞尔曲线的,即抛物线,其方法签名是public void quadTo (float x1, float y1, float x2, float y2),如果对贝塞尔曲线的相关概念不了解,推荐大家读一下博文《贝塞尔曲线初探》 。下面借用该博文中的一张图说一下二阶贝塞尔曲线: 
      这里写图片描述 
      二阶贝塞尔曲线的绘制一共需要三个点,一个起点,一个终点,还要有一个中间的控制点。我们画笔的位置就相当于上图中P0的位置,quadTo中的前两个参数x1和y1指定了控制点P1的坐标,后面两个参数x2和y2指定了终点P2的坐标。上图中最后一行的第四个线状图形就是用quadTo绘制的二阶贝塞尔曲线。

    • cubicTo跟quadTo类似,不过是用来画三阶贝塞尔曲线的,其方法签名是public void cubicTo (float x1, float y1, float x2, float y2, float x3, float y3)。我们还是借用一下上述博文《贝塞尔曲线初探》中的另一张图片来解释一下三阶贝塞尔曲线: 
      这里写图片描述 
      三阶贝塞尔曲线的绘制需要四个点,一个起点,一个终点,以及两个中间的控制点,也就是说它比二阶贝塞尔曲线要多一个控制点。我们画笔的位置就相当于上图中P0的位置,cubicTo中的前两个参数x1和y1指定了第一个控制点P1的坐标,参数x2和y2指定了第二个控制点P2的坐标,最后两个参数x3和y3指定了终点P3的坐标。上图中最后一行的最后一个线状图形就是用cubicTo绘制的三阶贝塞尔曲线。

  4. 上面提到Path的moveTo方法移动了画笔的位置,这样说不准确,因为Path和Paint没有任何关系,准确的说法是移动了Path的当前点,当我们调用lineTo、arcTo、quadTo、cubicTo等方法时,首先要从当前点开始绘制。对于lineTo、quadTo、cubicTo这三个方法来说,Path的当前点作为了这三个方法绘制的线条中的起始点,但是对于arcTo方法来说却不同。当我们调用arcTo方法时,首先会从Path的当前点画一条直线到我们所画弧的起始点,所以在使用Path的arcTo方法前要注意通过调用Path的moveTo方法使当前点与所画弧的起点重合,否则有可能你就会看到多了一条当前点到弧的起点的线段。moveTo可以移动当前点,当调用了lineTo、arcTo、quadTo、cubicTo等方法时,当前点也会移动,当前点就变成了所绘制的线条的最后一个点。

  5. 上面提到了moveTo、lineTo、arcTo、quadTo、cubicTo的方法中传入的坐标都是绘图坐标系中的坐标,即绘图坐标系中的绝对坐标。其实我们可以用相对坐标调用这些类型功能的方法。Path因此提供了对应的rMoveTo、rLineTo、rQuadTo、rCubicTo方法,其形参列表与对应的方法相同,只不过里面传入的坐标不是相对于当前点的相对坐标,即传入的坐标是相对于当前点的偏移值。

  6. lineTo、arcTo、quadTo、cubicTo等方法只是向Path中添加相应的线条,只有执行了canvas.drawPath(path3, paint)方法时,我们才能将Path绘制到Canvas上。


drawBitmap

Canvas中提供了drawBitmap方法用于绘制Bitmap,其使用代码如下所示:

<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">private void drawBitmap(Canvas canvas){        //如果bitmap不存在,那么就不执行下面的绘制代码        if(bitmap == null){            return<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>        }        //直接完全绘制Bitmap        canvas<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.drawBitmap</span>(bitmap, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, paint)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>        //绘制Bitmap的一部分,并对其拉伸        //srcRect定义了要绘制Bitmap的哪一部分        Rect srcRect = new Rect()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>        srcRect<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.left</span> = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>        srcRect<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.right</span> = bitmap<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getWidth</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>        srcRect<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.top</span> = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>        srcRect<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.bottom</span> = (int)(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0.33</span> * bitmap<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getHeight</span>())<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>        float radio = (float)(srcRect<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.bottom</span> - srcRect<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.top</span>)  / bitmap<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getWidth</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>        //dstRecF定义了要将绘制的Bitmap拉伸到哪里        RectF dstRecF = new RectF()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>        dstRecF<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.left</span> = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>        dstRecF<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.right</span> = canvas<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getWidth</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>        dstRecF<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.top</span> = bitmap<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getHeight</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>        float dstHeight = (dstRecF<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.right</span> - dstRecF<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.left</span>) * radio<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>        dstRecF<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.bottom</span> = dstRecF<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.top</span> + dstHeight<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>        canvas<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.drawBitmap</span>(bitmap, srcRect, dstRecF, paint)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li></ul>

界面如下所示: 
这里写图片描述

我在res/drawable目录下放置了一张android的图片,下面对上面的代码进行说明:

  1. Canvas的drawBitmap有多个重载方法,最简单的方法签名是:

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

    该方法除了传入bitmap对象外,还需要传入left和top,left和top组成了一个坐标,决定了在Canvas中从哪个地方绘制Bitmap。在我们的代码中,left和top都设置为0,所以我们就在Canvas的左上角绘制了bitmap。

  2. drawBitmap还有一个比较实用的方法,其方法签名是:

    public void drawBitmap (Bitmap bitmap, Rect src, Rect dst, 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中的长宽比相同,这样不会导致图片长宽比例变形,效果见上图中的第二个放大的图形。

  3. 此处有一点需要说明,在绘图结束退出Activity的时候,我们需要调用bitmap的recyle()方法,防止内存泄露,本程序在onDestroy()方法中执行了该方法。


总结

  1. Canvas通过drawXXX等一些列的绘图方法决定了要绘制的图形的外形,我们可以通过自由组合绘制出我们想要的效果。drawXXX方法中的坐标都是基于当前绘图坐标系的坐标,而非Canvas坐标系,默认情况下二者重合。通过调用translate、rotate、scale等方法可以对绘图坐标系进行变换。

  2. 画笔Paint控制着所绘制的图形的具体外观,Paint默认的字体大小为12px,在绘制文本时我们往往要考虑密度density设置合适的字体大小。画笔的默认颜色为黑色,默认的style为FILL,默认的cap为BUTT,默认的线宽为0,参见下图所示: 
    这里写图片描述

  3. 在画面状的图形时,如果Paint的style是FILL,那么绘制的就是填充面;如果是STROKE,那么绘制的就是轮廓线。

代码为Android Studio工程,已上传到CSDN,点此下载

感谢大家耐心读完,希望文本对大家了解Canvas中的绘图基础有所帮助!

1 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 大石退出菊丸怎么办 word空白页面突然变大了怎么办 高速上车胎爆了怎么办 没有定速巡航跑长途怎么办 惠普笔记本驱动无法安装怎么办 狙击手遇到热追踪导弹怎么办 做完卷腹脖子疼怎么办 医疗设备销售遭遇瓶颈怎么办 给顾客加油加超了怎么办 卡密码输错两次怎么办 擤鼻涕耳朵会响怎么办 鼻子里有血丝是怎么办 怀孕8周上火了怎么办 鼻炎犯了鼻涕流不停怎么办 擤鼻涕眼睛肿了怎么办 感冒咳嗽鼻子不通气怎么办 宝宝感冒不会擤鼻涕怎么办 新生儿鼻腔里有鼻涕怎么办 宝宝鼻腔有鼻涕出不来怎么办 怀孕的人感冒了怎么办 孕37周感冒咳嗽怎么办 吹鼻涕耳朵堵了怎么办 怀孕的孔雀鱼生病了怎么办 生病了咳嗽一直不好怎么办 宝宝生病治疗后咳嗽怎么办 2个月宝宝老是生病怎么办 2个月的哈士奇生病怎么办 怀孕的猫生病了怎么办 宝宝生病咳嗽啥都不吃怎么办 怀孕了感冒了怎么办啊 2个月宝宝生病了怎么办 刚刚怀孕了就生病了怎么办 一岁多宝宝总是发烧咳嗽生病怎么办 7个月宝宝生病怎么办 4个月宝宝老是生病怎么办 孕早期嗓子有痰怎么办 鼻炎早晨起床鼻涕带血怎么办 鼻子破皮了结痂怎么办 擤鼻子耳朵好像堵住了怎么办 鼻子和脸上起皮怎么办 鼻子擦鼻涕擦红怎么办