本文介绍了Android的View动画中的旋转动画的应用及SquareLoading源码解析。
《冬夜读书示子聿》
古人学问无遗力,少壮工夫老始成。
纸上得来终觉浅,绝知此事要躬行。
–陆游
在前面的文章中,我们介绍了View动画、帧动画和属性动画的使用。
既然动画的基本使用我们都会了,那就从网上找一个动画来试着实现一下吧。从MaterialUp上面还真找到一个简单一点的动画:Animated Loader
乍一看还挺惊艳的,我们先来分析一下这个动画,动画中为12个方块,很简单的旋转90度的动画,我们先来实现一个方块的动画,使用GradientDrawable创建方块:
1 | GradientDrawable gradientDrawable = new GradientDrawable(); |
旋转中心点为左下角,旋转角度为90,持续时间为300ms,设置减速插值器,设置动画结束后延时300ms执行反转动画,同样反转动画结束后延时300ms重新开始执行动画:
1 | RotateAnimation startAnim = new RotateAnimation(0, -90, 0, mSquareSize); |
这样当调用startRotateAnim方法就可以看到效果了,接下来我们在上面的基础上实现12个方块的动画,上面的图片需要添加12个,我们通过继承ViewGroup自定义View实现,这里我们设置默认X的个数为4,Y的个数为3:
1 | public class SquareLoading extends ViewGroup { |
其中DEFAULT_FIRST_INDEX和DEFAULT_LAST_INDEX分别表示第一个开始动画子View的index和最后一个开始动画子View的index。例如,当x=4,y=3时,第一个开始执行开始动画的子View的index为8,最后一个执行开始动画的子View的index为3,当然,这也对应反转动画的最后一个和第一个:
一个完整的自定义View对应的属性肯定是可以配置的,比如方块的数量、大小和颜色等:
1 | if (attrs != null) { |
添加图片之前有一个细节需要处理,因为我们是继承ViewGroup自定义的View,所以要防止用户添加其它子View:
1 | if (getChildCount() > 0) { |
接下来根据配置的方块的个数添加子View:
1 | for (int i = 0; i < mXCount * mYCount; i++) { |
因为每个子View都有对应的开始动画和反转动画,所以我们使用List来存储对应子View的动画,动画和只有一个方块时的区别是当第一个子View动画开始时需要延时执行下一个子View的动画,当所有子View开始动画结束后开始逆向执行反转动画,如此反复:
1 | private List<RotateAnimation> startAnims = new ArrayList<>(); |
其中getNextAnimChild方法为获取下一个要执行动画的子View的index。
最后根据用户设置的宽高测量子View并布局:
1 | @Override |
最终效果:
查看完整源码:https://github.com/yuweiguocn/SquareLoading
