大家都知道Android常见的动画有tween动画,frame动画。但是随着人们对动画的要求不断提高,上述两种方式已经不能实现一些复杂的动画效果,所以在3.0(API 11)以后提供了另外的一种强大的动画——属性动画。所谓的属性动画,即可以改变对象的属性来实现动画,比如tween动画实现平移效果,但是对象的变化过程中的动画却无法实现,属性动画可以在实现动画的过程中改变对象的某些属性来实现复杂的动画,某种意义上讲,属性动画可以替代tween动画。tween动画有一定的局限性,动画完成以后虽然改变了原来的位置,但是这时候你去点击对象是不会触发点击事件的,因为tween动画只是改变了原来对象的位置,相当于重绘了一次。但是控件的实际位置还是原来的位置。属性动画就很好的解决了这一问题,属性动画改变的是空间的属性信息来实现动画效果的。
ValueAnimator是属性动画的一个核心类之一。ValueAnimator完成了动画从初始值到结束值之间的计算过程,我们只需要给出变化的初始值和结束值即可,当然他还可以设置动画的播放模式、播放次数、设置监听器等。下面我们来看一下他的使用方法。
ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f); anim.setDuration(300); anim.start();
代码很简单,首先利用ofFloat设置了动画的初始值和结束值,表示动画从0到1的变化过程,当然可以传入多个值,例如ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f,2f,3f);表示动画从0到1,再到2再到3的过程。然后设置了持续时间,也就是300毫秒内从0到1。那到底0到1的过程是不是随时变化的呢,我们来设置一个监听函数来打印一下log。
ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f); anim.setDuration(300); anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float currentValue = (float) animation.getAnimatedValue(); Log.d("TAG", "cuurent value is " + currentValue); } }); anim.start();
通过添加addUpdateListener来监听动画过程中的变化情况,Log打印:
除了ofFloat()以外还有ofInt()、ofObject()方法。
ObjectAnimator相对ValueAnimator更常用一些,他可以具体到对某个VIEW的动画操作,比如实现对一个控件的平移旋转等操作。
ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "rotation", 0f, 360f); animator.setDuration(5000); animator.start();
上述代码实现了对一个textview旋转360度的动画,当然下面这段代码实现了透明度从1到0再到1的 变化。
ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "alpha", 1f, 0f, 1f);
当然我们还可以传入“translationY”Y轴平移;“translationX”X轴平移;"scaleX"X轴放大;"scaleY"Y轴放大
有了单个的动画,当然也可以把他们组合起来使用。把它们组合起来就要用到AnimatorSet这个类了,这个类有一个play()方法,传入一个Animator(ObjectAnimator或ValueAnimator)对象,返回一个AnimatorSet.Builder实例,实例包含下面四个方法:
after(Animator anim) 将现有动画插入到传入的动画之后执行
after(long delay) 将现有动画延迟指定毫秒后执行
before(Animator anim) 将现有动画插入到传入的动画之前执行
with(Animator anim) 将现有动画和传入的动画同时执行
有了这四个方法就可以对动画进行组合使用了。比如我们要实现同时旋转透明度在平移之后进行,代码如下:
ObjectAnimator moveIn = ObjectAnimator.ofFloat(textview, "translationX", -500f, 0f); ObjectAnimator rotate = ObjectAnimator.ofFloat(textview, "rotation", 0f, 360f); ObjectAnimator fadeInOut = ObjectAnimator.ofFloat(textview, "alpha", 1f, 0f, 1f); AnimatorSet animSet = new AnimatorSet(); animSet.play(rotate).with(fadeInOut).after(moveIn); animSet.setDuration(5000); animSet.start();
在很多时候,我们希望可以监听到动画的各种事件,比如动画何时开始,何时结束,然后在开始或者结束的时候去执行一些逻辑处理。这个功能是完全可以实现的,Animator类当中提供了一个addListener()方法,这个方法接收一个AnimatorListener,我们只需要去实现这个AnimatorListener就可以监听动画的各种事件了。
大家已经知道,ObjectAnimator是继承自ValueAnimator的,而ValueAnimator又是继承自Animator的,因此不管是ValueAnimator还是ObjectAnimator都是可以使用addListener()这个方法的。另外AnimatorSet也是继承自Animator的,因此addListener()这个方法算是个通用的方法。
添加一个监听器的代码如下所示:
anim.addListener(new AnimatorListener() { @Override public void onAnimationStart(Animator animation) {//动画开始调用 } @Override public void onAnimationRepeat(Animator animation) {//动画重复调用 } @Override public void onAnimationEnd(Animator animation) {//动画结束调用 } @Override public void onAnimationCancel(Animator animation) {//动画取消调用 } });
这个接口实现了四个方法,有时候可能我们并不需要这么多的方法。怎么办呢?Android还给我们提供了一个AnimatorListenerAdapter类,代码如下:
anim.addListener(new AnimatorListenerAdapter() { //在下面重写你需要实现的方法 @Override public void onAnimationEnd(Animator animation) { } });
通过上面的介绍,属性动画的基本用法我们已经能够熟悉了,要想实现更复杂的动画还需要学习属性动画的高级用法,下一篇博客我们将介绍他的高级用法。