之前说想要写一篇自动补全的EditText,不过后来随便写了一下,发现并没有想象中的简单,加上最近项目进度一直在赶,没时间认认真真捣鼓了,看到腾讯的手机管家加速球还不错,而且实现起来逻辑不是很复杂,所以这周就尝试如何实现加速球这种动画效果。
先来看看手机管家的加速球是什么样的
功能需求
这个控件大概需要实现三个部分的功能
1、在最底层画出一个圆
2、画出底层的小波浪和外层的大波浪(一开始我以为这两个波浪是分开的,后来发现合在一起更加好实现)
3.添加横向的动画,设置一个修改水位的纵向动画
4、我发现手机管家在水位下降之后没有根据当前的手机内存耗用情况把刷新水位,虽然我不是很理解,不过我认为应该加上的,添加一个回调。
知识点,也是难点
首先肯定是先定义一个BallView继承自View类了,接着重写onDraw方法。那么在重写onDraw方法之前,先介绍一下今天涉及到canvas的一些知识,但是都不会扩展来讲,因为要学好自定义控件,以下的东西都必须要掌握的:
贝塞尔曲线:关于贝塞尔曲线,我想学习过自定义控件的人都会接触到,因为它对于绘制曲线非常的强大,而我们大多数情景下绘制的东西都不是标准的圆或者矩形。
setXfermode():这是Paint里面的一个API,设置图片相交模式,对于多图层叠的时候,这个函数就会非常的强大,虽然设置起来很简单,但是要理解记住每一种模式也是相当困难的。
离屏绘制:涉及到Canvas的图层概念,虽然简单来说只有两行代码。
接下来就是正文部分了,因为这个功能很简单,而且对于尝试自定义控件的朋友会觉得蛮有意思的吧,所以我就按着我自己的思路直接从代码上来讲解如何实现这个动画效果了:
1、我们知道画笔对象其实就那么几个,就好比如我们画画的时候,首先需要准备好纸画笔颜料这些零零碎碎的东西,纸就是系统提供给我们的Canvas对象了,而至于画笔我们需要提前准备好:
不知道大家有没有用过TakeColor这个取色工具,上面的颜色就是用这个工具取得,以后要是我们独立开发的时候看到好的颜色搭配,可以直接用这个工具就知道颜色的RGB值了。
2、接下来就是今天想重点讲解的部分了,我们都知道贝塞尔曲线能够画出波浪形的圆滑的路径,但是要怎么滑还是需要斟酌斟酌,像手机管家中的加速球的波浪是有内外两层的,这样给人一种立体感,用户体验也就蹭蹭上去了。毕竟,用户体验就是用户使用过程中的感觉吗,细节很重要啊。接下来就看看这个自定义控件是如何进行绘图的吧:
onDraw:
在这里可以看到一共调用了canvas的两次draw方法,所画即所得:
画圆:
必须加一个背景,不然图层混合后,两个图层重合部分的透明区域都会消失,重叠之后就看不到波浪的圆背景了。如下图所示:
画内层小波浪:
小波浪的路径其实是有讲究的,要是小波浪跟大波浪的路径方向是一样的,即从左到右,你就会发现压根看不出波浪流动的效果了,因为大小波浪都往同一个方向匀速地运动,那么他们相对是静止的。这个时候我想有两个方法,第一个方法是设置两个速率不一样的属性动画,那么我们就可以看到这两个动画相对是
运动
的。不过这里我用的是第二个方法,用的是同一个属性动画,但是大波浪是从左到右,而小波浪是从右到左的。这样不管速率问题,他们相互都是
运动
的。最后稍微添加一点水平方向的偏移量,设置rQuad的第一个参数,也就是转点的坐标均小于大波浪的转点坐标,就可以实现前浪(大波浪)比后浪(小波浪)更大的效果。PS:水平偏移量跟波浪的波峰我想是有关联的,不过具体如何这里就无从考究了。
这里再说一下具体的路径是怎么考虑的。我们绘制组件的时候,最困扰我们的可能是Path路径的创建,有了路径,剩下的就只是上色还有两个图层重叠时如何显示了。
mWaveLength:一个波浪(有起有伏)的长度,如果波浪长度少于控件的宽度,那么控件就会显示多个波浪,在这里这个值设置为控件的实际宽度,而转点的x坐标决定波峰在波浪中的水平位置。
d_value:动画在水平方向上的偏移量,因为这个偏移量是波浪的一个周期,所以for循环的起点是-mWaveLength+getX(),这样不管d_value怎么改变,波浪不会"断"掉,那么终点为什么设置为getWidth+mWaveLength呢,这里纯粹是逻辑上视图更加连贯而已。
画外层大波浪:
这里大致上和获取小波浪是一样的,不一样的地方是,起始点moveTo的坐标,大波浪的起点是从左到右的,水位线startPosition就是我们设定的值。
该画的部分都已经画完了,接下来就是动画部分了。动画部分难度不大,动画的速度就是波浪流动的速度,所以duration不要设置的太小。总体来说都不复杂,只是要实现流动很自然的效果,就要用点心了。直接贴代码了
水平方向的动画(波浪流动)
竖直方向的动画(设置水位,水位上升下降的动画)
整个控件制作过程就是这样了,难度要比EditText简单很多很多,当然跟那些很炫很炫的控件是没法比的,尤其是跟数据绑定在一起的控件,至于手机管家上的那个小飞机,pressed的时候飞机放大,点击的时候飞机上升,水位下降,然后飞机再从底下升起来,这些实现起来都不难,但是这些效果这里不扩展了。
所以最终实现出来的效果是
以后有空再写一篇图层混合模式还有View事件的分发消费拦截,感觉像我这样的新手学习这两个东西的时候总是不得要领!得先把狠话搁下了督促一下自己才行-_-||,妈的最近压力好大,债台高筑啊