概述
最近看到一个bootstrap的loading框,感觉还挺好看的,决定动手写一个。首先来技术选型一下吧,其实一个loadingview在这里扯性能问题并不是很合适,但是如果一定要讨论用什么去实现的话,我认为其事SurfaceView是个不错的选择,原因在于我们是主动的更新界面,根据数据去运算,所以,这种主动更新的场景更加适合SurfaceView来实现,刚好最近写了一片关于SurfaceView的入门博客,拿来练练手挺不错的。
示例
先来看看本文最后的结果长啥样子吧。
12个旋转的球

5个花色球型的脉冲

5个同色的矩形脉冲

SurfaceView回顾
由于拥有独立的绘图表面,因此SurfaceView的UI就可以在一个独立的线程中进行绘制。又由于不会占用主线程资源,SurfaceView一方面可以实现复杂而高效的UI,另一方面又不会导致用户输入得不到及时响应。总之就是夸奖SurfaceView很牛逼啦,但是牛逼的同时,也是会有坑的哦。
SurfaceView使用的几个步骤
SurfaceView使用的步骤主要包括:
- 首先继承自SurfaceView,实现最基本的几个构造函数,在构造函数里初始化最基本的绘图数据。
- 在构造函数里,获取SurfaceHolder示例,保存在一个变量里,该句柄便于后面线程中绘画使用。
- 为holder添加一个callback函数,用来出发SurfaceView各个阶段的操作。为了代码简洁,直接将外层类继承自SurfaceView.CallBack,并执行addCallBack。
- 这个Callback一共有三个方法要去覆写,分别是1234567891011121314public void surfaceCreated(SurfaceHolder holder) {}public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}public void surfaceDestroyed(SurfaceHolder holder) {}
三个方法分别会在创建,可见度改变,和不可见的时候触发。所以在使用的时候,我们要调用SurfaceView的setVisibility方法来控制其生命周期。
- 在创建区域surfaceCreated进行绘图相关的初始化工作,比如Paint,循环线程的开始操作。
- 在不可见销毁区域surfaceDestroyed关闭线程,个人认为最好的退出循环线程的方法是使用变量标志位。
- 在创建的线程里,一般首先调用holder.lockCanvas来获取画布,或者调用lockCanvas(RectF)来锁定脏数据区域。然后进行各种异想天开的绘画,这时候,世界就交给你了。
基本上知道以上的步骤,就大概了解这东西怎么用了,当然也有写注意点的,如何设置背景透明,绘图清除区域颜色等,还有线程更新时间等。
矩形脉冲
基本思路
首先是订基本参数咯,我们的边框是多少,这就需要定义containerWidth,containerHeight,这个可以在surfaceCreated以后,通过api获取,然后我们的总长度是多少totalWidth,一共绘制几个count,每个之间的宽度是多少xGap,每个矩形的基本高度是多少baseHeight,矩形的振幅AMPLITUDE等。如下:
定义runnable
我们要循环的制造脉冲,那么需要在runnable中定义一个循环事件,解释起来太难了,直接上代码吧,
照着代码来解释可能简单些,先计算容器高宽,知道自己的绘制空间,计算起始绘制点startX和startY,计算出脏数据区域,依次绘制出count个矩形,其高度的计算是核心,绘制出这些矩形后,提交更新。并将线程睡眠10毫秒,这里取10毫秒是因为动画的最小单元就是10,我们也是在做动画,没必要搞得很快,给及其带来压力,同时也不能太慢,这样会有明显的视觉错误。
制造脉冲发生器
在脉冲发生器上,每个人可能都有自己的想法去实现,我都想了好几种,最后还是想到了去正弦线上去截数据的办法,即将0-PI/2的空间分成count份,并将小于0的部分割掉,那么脉冲就形成了啊,但是这个脉冲是比较缓的。代码如下:
好了,至此,我们就完成了矩形的发生器loadingView了,按照这个思路,我们可以写出各种各样的脉冲型loadingView,当然不一定是loadingView哈,现在你就是画家了,想怎么画就怎么画,期待大家的master piece啦。
矩形完整的代码
在博客里不想贴太多代码,那么就贴一个矩形的代码吧,其他的代码我做成了android library放在了github上,如果感兴趣的话,可以到我的个人空间下去下载。
下载地址是 https://github.com/gordon-rawe/loadingview.git
总结
其实使用VectorAnimator也可以用一些xml就搞定,但是好像API有限制,接下来想做一个从一个形状编程另一个形状的动画,期待我的作品吧!