360的水波进度提示-path绘图

今天使用自定义view实现类似于360的水波进度提示的功能,效果如下: 
360的水波进度提示-path绘图_第1张图片

实现原理

实现该效果主要用到了使用path绘制正弦波,以及xfermode知识点。可以首先绘制一个实心圆,然后设置xfermode为SRC_ATOP。

path快速学习

我们先来简单看一下path的基本用法,path可以绘制任何我们想要的图形。

<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;">mPath = new Path()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
mPath<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.lineTo</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</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;">.drawPath</span>(mPath, mPaint)<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></ul>

360的水波进度提示-path绘图_第2张图片 
上面通过lineTo方法画了一条线,注意这里我没有设置起始点,默认为该view的左上角,注意,是该view的左上角,而不是屏幕的左上角,这里是因为我们的view宽和高都是match_parent。

<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;">mPath = new Path()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
mPath<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.moveTo</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">50</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">50</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
mPath<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.lineTo</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</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;">.drawPath</span>(mPath, mPaint)<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></ul>

360的水波进度提示-path绘图_第3张图片 
可以看到此时通过moveTo方法将起始点设置到(50,50)。

<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;">mPath = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Path();
mPath.moveTo(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">50</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">50</span>);
mPath.arcTo(<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;">50</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">50</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">300</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">450</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;">180</span>,<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>);
canvas.drawPath(mPath, mPaint);</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></ul>

360的水波进度提示-path绘图_第4张图片 
这里使用arcTo方法在矩形内切一个圆弧,当然如果该矩形是一个正方形,那就是圆了,这里我的其实角度是0度,终止角度是180,第四个参数表示是否强制将起始点移动到绘制圆弧的起始点,这么说可能不是很好理解,我们将第四个参数更改为true,效果如下: 
360的水波进度提示-path绘图_第5张图片 
可以看到此时绘制椭圆时候的起始点就是其起始点。

<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;">mPath = new Path()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
mPath<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.moveTo</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">200</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">200</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
mPath<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.lineTo</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">300</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">300</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
mPath<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.lineTo</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">300</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
mPath<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.lineTo</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">200</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">200</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;">.drawPath</span>(mPath, mPaint)<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></ul>

360的水波进度提示-path绘图_第6张图片 
这里根据给定的三个点,绘制了一个三角形,最后的mPath.lineTo(200,200);主要是首位相接,保证最后一个点和第一个点连接,其实不必这么麻烦,可以使用Path提供的close()方法,保证线条闭合。

<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;">mPath = new Path()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
mPath<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.moveTo</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">200</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">200</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
mPath<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.lineTo</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">300</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">300</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
mPath<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.lineTo</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">300</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
mPath<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.close</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;">.drawPath</span>(mPath, mPaint)<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></ul>

此时效果和上面是相同的。

另外path还提供了一系列addXX方法,用来在一个path中绘制多个图形。如下:

<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;">int width = getWidth()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
int height = getHeight()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
mPath = new Path()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
int radius = Math<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.min</span>(width, height) / <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>

mPath<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.addCircle</span>(width / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, height / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>,radius , Direction<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.CCW</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>

mPath<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.addRoundRect</span>(new RectF(width / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> - radius / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> , height / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> - radius / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, width / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> + radius / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>,height / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> + radius / <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;">20.0</span>f,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">20.0</span>f,Path<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.Direction</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.CCW</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>

mPath<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.addOval</span>(new RectF(width / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> - radius / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>, height / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> - radius / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>, width / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> + radius / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>,height / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> + radius / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>),Path<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.Direction</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.CCW</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;">.drawPath</span>(mPath, mPaint)<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></ul>

 
可以看到,这里我连续给path中add了三个图形,当然也可以通过”mPath.addPath(src)”方法,将另一个path描绘的图形,添加到当前的path中。

绘制贝塞尔曲线: 
我们可以使用path提供的quadTo(x1, y1, x2, y2)方法来绘制任何形状的曲线。 
x1, y1表示控制点的坐标 
x2, y2表示终点的坐标

<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;">mPath = new Path()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
mPath<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.moveTo</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">300</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
mPath<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.quadTo</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">150</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">200</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">200</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">300</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;">.drawPath</span>(mPath, mPaint)<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-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">300</span>,mPointPaint)<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-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">150</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">200</span>,mPointPaint)<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-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">200</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">300</span>,mPointPaint)<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></ul>

此时效果如下: 
360的水波进度提示-path绘图_第7张图片 
可以看到这样就绘制了我们半个周期的正弦曲线,使用两个quadTo方法绘制一个完整的正弦曲线:

<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;">mPath = new Path()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
mPath<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.moveTo</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">300</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
mPath<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.quadTo</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">150</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">200</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">200</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">300</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
mPath<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.quadTo</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">250</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">400</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">300</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">300</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;">.drawPath</span>(mPath, mPaint)<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-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">300</span>,mPointPaint)<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-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">150</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">200</span>,mPointPaint)<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-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">200</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">300</span>,mPointPaint)<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-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">250</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">400</span>,mPointPaint)<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-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">300</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">300</span>,mPointPaint)<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></ul>

 
一个完整的正弦已经绘制完成,但是这样绘制正弦曲线还不把人累死?什么时候调用quadTo方法才是个头呢??还好android为我们提供了另外一个方法,cubicTo(x1, y1, x2, y2, x3, y3),用来绘制三阶贝塞尔曲线,这个方法就可以绘制一个完整的正弦声明周期啦。 
x1, y1 表示第一个控制点的坐标 
x2, y2 表示第二个控制点的坐标 
x3, y3 表示终点的坐标 
因此,上面的代码就可以简化如下:

<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;">mPath<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.cubicTo</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">150</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">200</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">250</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">400</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">300</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">300</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;">.drawPath</span>(mPath, mPaint)<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></ul>

效果如下: 
360的水波进度提示-path绘图_第8张图片

其实到这里还有一个问题,那就是如果需要绘制很多个正弦连在一起cubicTo方法也是相当的不方便,因为我们需要不断的计算控制点的坐标,不怕,android中的Path还为我们提供了一些列rxxx的方法,比如rLineTo(dx, dy)方法,其实该方法和lineTo(dx, dy)的作用是一样的,唯一不同的地方在于,rLineTo(dx, dy)方法会将上一个点的坐标当成起始坐标而已,看下面的栗子:

<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;">mPath = new Path()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
mPath<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.moveTo</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
mPath<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.lineTo</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">200</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">200</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;">.drawPath</span>(mPath, mPaint)<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></ul>

360的水波进度提示-path绘图_第9张图片 
这里起始点坐标(100,100),划线的终点坐标(200,200)。

<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;">mPath = new Path()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
mPath<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.moveTo</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
mPath<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.rLineTo</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">200</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">200</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;">.drawPath</span>(mPath, mPaint)<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></ul>

360的水波进度提示-path绘图_第10张图片 
可以看到这里rLineTo方法将上一个点的坐标当成其实坐标(0,0)点来计算

水波进度实现

有了上面Path绘制曲线的基础以后,下面带大家一步一步实现水波进度的效果。

绘制连续的正弦曲线

由于rQuadTo方法是会将上一个坐标点当成起始坐标(0,0)点,也就是说其使用的是相对坐标,那么我们可以多次调用rQuadTo方法来绘制连续的正弦曲线,而不用计算那些烦人的控制点坐标。

<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;">mPath<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.reset</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
mPath<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.moveTo</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
for (int i = <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;">; i < 3; i++) {</span>
    mPath<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.rQuadTo</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">30</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">40</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">60</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>
    mPath<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.rQuadTo</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">30</span>, -<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">40</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">60</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>
}
canvas<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.drawPath</span>(mPath, mPaint)<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></ul>

360的水波进度提示-path绘图_第11张图片

这里我绘制了三条正弦曲线,原理如下图: 
 
可以看到,这里的rQuadTo使用的是相对坐标,即将上一个点的坐标作为起始点(0,0),所以我们才不用计算控制点的坐标。

让曲线动起来

下面我们每次更改正弦曲线起始点的x坐标,并且不断重绘,来使当前正弦曲线动起来。

<code class="hljs java 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;">new</span> Thread(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Runnable() {
            <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</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;">run</span>() {

                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">while</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</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;">if</span> (mStartX < <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">80</span>) {
                        mStartX += <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;">else</span> {
                        mStartX = <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>
                    mSinMax += <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;">if</span> (mShouldUp) {
                        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mSinMax > <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">20</span>) {
                            mShouldUp = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;
                        }
                    } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {
                        mSinMax -= <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;">if</span> (mSinMax < -<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">20</span>) {
                            mShouldUp = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;
                        }
                    }


                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> {
                        Thread.sleep(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">200</span>);
                    } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (InterruptedException e) {
                        e.printStackTrace();
                    }

                    postInvalidate();
                }
            }
        }).start();

<span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">protected</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;">onDraw</span>(Canvas canvas) {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>.onDraw(canvas);

        mPath.reset();
        mPath.moveTo(mStartX,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>);
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> i = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; i < <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span>; i++) {
            mPath.rQuadTo(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">20</span>, mSinMax, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">40</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>);
            mPath.rQuadTo(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">20</span>, -mSinMax, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">40</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>);
        }
        canvas.drawPath(mPath, mPaint);
    }</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></ul>

在这里,我通过线程不断改变当前曲线的其实绘制坐标,以及当前震动的幅度。此时效果如下: 

一张图看懂原理

请看下面的图: 
 
是不是有点恍然大悟的赶脚,对,只要在中间绘制一个圆,在加之以xfermode的使用,就完成了我们最开始的效果。 
这里整个图形的绘制代码如下:

<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;">mPath<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.moveTo</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">450</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">; //矩形右上角</span>
mPath<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.lineTo</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">450</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">300</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">; //矩形右下角</span>
mPath<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.lineTo</span>(mStartX,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">300</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">; //矩形左下角</span>
mPath<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.lineTo</span>(mStartX, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">; //矩形左上角</span>
for (int i = <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;">; i < 5; i++) {</span>
    mPath<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.rQuadTo</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">20</span>, mSinMax, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">40</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>
    mPath<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.rQuadTo</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">20</span>, -mSinMax, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">40</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>
}
canvas<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.drawPath</span>(mPath, mPaint)<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></ul>

可以看到这里实际上就是绘制了一个矩形,并且让该矩形的x轴随着当前正弦曲线需要的起始点移动,并且绘制5个正弦曲线。 
 
可以看到这里我们需要使用SRC_ATOP或者DST_ATOP这两种模式中的一个。

具体实现

使用到的属性

<code class="hljs java 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> Paint mPaint;   <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;">private</span> Paint mCirclePaint; <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;">private</span> Path mPath;  <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;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> width;  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//自定义view的宽度</span>
<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;">int</span> height; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//自定义view的高度</span>
<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;">int</span> mCirclePaintRadius;  <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;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> mStepSize;  <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;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> mMoveStartX;  <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;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> mSinMax;  <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;">private</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-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;">private</span> Canvas mCircleCanvas;  
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> Bitmap mDest;
<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;">int</span> mCurrentProgress;  <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;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> shouldChange;  <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;">private</span> Paint mTextPaint;

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> Rect mBound;</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>

初始化方法

<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 init() {
//设置绘制水波画笔的属性
mPaint=new Paint(Paint<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.ANTI</span>_ALIAS_FLAG)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
mPaint<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setColor</span>(Color<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.parseColor</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"#99FF99"</span>))<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
mPaint<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setAntiAlias</span>(true)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
mPaint<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;">5</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
mPaint<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setStyle</span>(Paint<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.Style</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.FILL</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
PorterDuffXfermode mode = new PorterDuffXfermode(PorterDuff<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.Mode</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.SRC</span>_ATOP)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
mPaint<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setXfermode</span>(mode)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>

mPath = new Path()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>

//设置绘制背景圆的画笔属性
mCirclePaint = new Paint(Paint<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.ANTI</span>_ALIAS_FLAG)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
mCirclePaint<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setStyle</span>(Paint<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.Style</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.FILL</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
        mCirclePaint<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setColor</span>(Color<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.parseColor</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"#CCCCFF"</span>))<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
mCirclePaint<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;">5</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>

//绘制文字的画笔
mTextPaint = new Paint(Paint<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.ANTI</span>_ALIAS_FLAG)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
mTextPaint<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setTextSize</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>
mTextPaint<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setColor</span>(Color<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.parseColor</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"#3399FF"</span>))<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>

mBound = new Rect()<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></ul>

可以看到我在初始化方法中,初始化了三个画笔,以及path,rect等。

计算初始值

在onMeasure方法中根据当前view的大小计算圆形,以及正弦曲线的周期等。

<code class="hljs java 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-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">protected</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;">onMeasure</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> widthMeasureSpec, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> heightMeasureSpec) {
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>.onMeasure(widthMeasureSpec, heightMeasureSpec);
    width = getMeasuredWidth();
    height = getMeasuredHeight();

    mCirclePaintRadius = Math.min(width,height) / <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;">//计算mStepSize(1/4周期)的大小</span>
    mStepSize = (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>) (Math.min(width,height) / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3.0</span>f * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>) / (count * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span>);

    mDest = Bitmap.createBitmap(width, height, Config.ARGB_8888);
    mCircleCanvas = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Canvas(mDest);
}</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></ul>

重写onDraw方法

下面重写onDraw方法来绘制当前的进度图形。

<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;">@Override
protected void onDraw(Canvas canvas) {
    super<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.onDraw</span>(canvas)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>

    //线绘制一个实心圆
    mCircleCanvas<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.drawCircle</span>(width / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, height / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, mCirclePaintRadius, mCirclePaint)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>

    //每次绘制记得调用reset()方法,否则当前绘制会和上次的绘制重叠
    mPath<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.reset</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
    //下面的moveTo,lineTo,lineTo,lineTo主要是让当前正弦线的首位相接
    mPath<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.moveTo</span>(width / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> + mCirclePaintRadius, height / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>
                + mCirclePaintRadius
                - (mCurrentProgress * (mCirclePaintRadius * <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;">100.</span>f)))<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
    mPath<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.lineTo</span>(width / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> + mCirclePaintRadius, height / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>
                + mCirclePaintRadius)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
    mPath<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.lineTo</span>(mMoveStartX, height / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> + mCirclePaintRadius)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
    mPath<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.lineTo</span>(mMoveStartX, height / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> + mCirclePaintRadius
                - (mCurrentProgress * (mCirclePaintRadius * <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;">100.</span>f)))<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>

    for (int i = <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;">; i < (count + 1); i++) {</span>
        mPath<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.rQuadTo</span>(mStepSize,mSinMax, mStepSize * <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>
        mPath<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.rQuadTo</span>(mStepSize,-mSinMax,mStepSize * <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>
        }
        mCircleCanvas<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.drawPath</span>(mPath, mPaint)<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>(mDest,<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>,null)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>

        //准备绘制当前进度
        String text = mCurrentProgress+<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"%"</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
        mTextPaint<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getTextBounds</span>(text, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, text<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.length</span>(), mBound)<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;">.drawText</span>(text, width / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> - mBound<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.width</span>() / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> , height / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> + mBound<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.height</span>() / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> , mTextPaint)<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>

改变初始位置和当前振幅

<code class="hljs java 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;">new</span> Thread(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Runnable() {

            <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</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;">run</span>() {
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">while</span> (mCurrentProgress < <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>) {

                    mMoveStartX += Math.random() * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">15</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;">//当当前初始位置 > 半个周期的时候,重新从头开始绘制</span>
                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mMoveStartX >= mStepSize) { 
                        mMoveStartX = <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;">if</span> (shouldChange) {  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//正弦线上升部分,mSinMax是振幅</span>
                        mSinMax++;
                        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mSinMax == <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) {
                            mSinMax = <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;">if</span> (mSinMax > <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">18</span>) {
                            shouldChange = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;
                        }
                    } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> { <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//正弦线下降部分</span>
                        mSinMax--;
                        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mSinMax == <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) {
                            mSinMax = -<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;">if</span> (mSinMax <= -<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">18</span>) {
                            shouldChange = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;
                            mSinMax = <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;">//                          mSinMax = 0;</span>
                        }
                    }
                    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//改变当前进度</span>
                    mCurrentProgress += Math.round(Math.random() * <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;">if</span> (mCurrentProgress >= <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>) {
                        mCurrentProgress = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>;
                        mSinMax = <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;">//当进度是100%的时候将振幅重置为0,这样就会填充整个圆形</span>
                    }

                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> {
                        Thread.sleep(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">300</span>);
                    } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (InterruptedException e) {
                        e.printStackTrace();
                    }
                    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//重新绘制当前view</span>
                    postInvalidate();
                }
            }
        }).start();</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></ul>

这里开启一个线程,不断的重新改变当前正弦曲线绘制的起始点坐标,并且不断重绘。上面的说明比较详细,这里我就不啰嗦了。

虽然看起来实现了一点效果,不过我个人觉得这样还是很不科学,比如由于该view还有很大的一部分我们是看不到的,但是仍然很占位置,这样就很不好,哪位大神有更好的思路也可以给予指导。


摘自

http://blog.csdn.net/mockingbirds/article/details/49804703


你可能感兴趣的:(水波,path函数)