您的位置:首页 > 移动开发 > Android开发

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

2015-11-23 14:22 501 查看
版权声明:本文为博主原创文章,未经博主允许不得转载。如果觉得文章不错,记得顶一下!如果有疑问觉得文章中有错误,欢迎大家在评论中给我留言指正,看到会及时回复,多多交流

目录(?)[+]

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>


界面如下所示:



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

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

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

通过调用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)的方式更简洁。

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

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

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

通过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>


界面如下所示:



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

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

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

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

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

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

drawLine

Canvas通过drawLine方法绘制一条线段,通过drawLines方法绘制多段线,使用代码如下所示:



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

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

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个值绘制一条线段的意思了。

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

上面在讲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>


界面如下所示:



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

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

当我们在调用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时,同时绘制填充面和轮廓线,不过这种情况用的不多,因为填充面和轮廓线是用同一种颜色绘制的,区分不出轮廓线的效果。

在Paint的style是FILL时,我们通过drawCircle绘制出圆面,如上图中的第一个图形所示。

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

除了上述方法,我们还有一种办法绘制圆环的效果。我们首先将画笔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>


其界面如下所示:



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

其方法签名是public void drawOval (RectF oval, Paint paint),RectF有四个字段,分别是left、top、right、bottom,

这四个值对应了椭圆的左、上、右、下四个点到相应坐标轴的距离,具体来说,left和right表示椭圆的最左侧的点和最右侧的点到绘图坐标系的y轴的距离,top和bottom表示椭圆的最顶部的点和最底部的点到绘图坐标系的x轴的距离,这四个值就决定了椭圆的形状,right与left的差值即为椭圆的长轴,bottom与top的差值即为椭圆的短轴,如下图所示:



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

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

如果我们想绘制带有其他颜色轮廓线的椭圆面,我们需要绘制两个椭圆。首先以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>


界面如下所示:



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

用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,表示在绘制完弧之后,弧的起点和终点直接连接,不经过椭圆的中心点。

在代码中我们一开始设置的Paint的style为FILL,即填充模式。通过上面的描述我们知道,drawOval方法可以看做是drawArc方法的一种特例。如果在drawArc方法中sweepAngle为360,无论startAngle为多少,drawArc都会绘制一个椭圆,如上图中第一个图形,我们用canvas.drawArc(rectF, 0, 360, true, paint)绘制了一个完整的椭圆,就像用drawOval画出的那样。

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

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

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

如果我们想绘制出带有其他颜色轮廓线的弧面时,该怎么办呢?我们可以分两步完成:首先,将画笔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>


界面如下所示:



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

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了,如上图中第一行中的几个图形所示。

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

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绘制的三阶贝塞尔曲线。

上面提到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等方法时,当前点也会移动,当前点就变成了所绘制的线条的最后一个点。

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

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的图片,下面对上面的代码进行说明:

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。

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

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

总结

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

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



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

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

感谢大家耐心读完,希望文本对大家了解Canvas中的绘图基础有所帮助!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: