ValueAnimator
ValueAnimator是整个属性动画机制当中最核心的一个类,前面我们已经提到了,属性动画的运行机制是通过不断地对值进行操作来实现的,而初始值和结束值之间的动画过渡就是由ValueAnimator这个类来负责计算的。它的内部使用一种时间循环的机制来计算值与值之间的动画过渡,我们只需要将初始值和结束值提供给ValueAnimator,并且告诉它动画所需运行的时长,那么ValueAnimator就会自动帮我们完成从初始值平滑地过渡到结束值这样的效果。除此之外,ValueAnimator还负责管理动画的播放次数、播放模式、以及对动画设置监听器等,确实是一个非常重要的类。
平移动画
比如说想要将一个值从0平滑过渡到1,时长300毫秒,就可以这样写:
- ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
- anim.setDuration(300);
- anim.start();
用法就是这么简单,现在如果你运行一下上面的代码,动画就会执行了。可是这只是一个将值从0过渡到1的动画,又看不到任何界面效果,我们怎样才能知道这个动画是不是已经真正运行了呢?这就需要借助监听器来实现了,如下所示:
- 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();
另外ofFloat()方法当中是可以传入任意多个参数的,因此我们还可以构建出更加复杂的动画逻辑,比如说将一个值在5秒内从0过渡到5,再过渡到3,再过渡到10,就可以这样写:
- ValueAnimator anim = ValueAnimator.ofFloat(0f, 5f, 3f, 10f);
- anim.setDuration(5000);
- anim.start();
ObjectAnimator
相比于ValueAnimator,ObjectAnimator可能才是我们最常接触到的类,因为ValueAnimator只不过是对值进行了一个平滑的动画过渡,但我们实际使用到这种功能的场景好像并不多。而ObjectAnimator则就不同了,它是可以直接对任意对象的任意属性进行动画操作的,比如说View的alpha属性。
,这里如果我们想要将一个TextView在5秒中内从常规变换成全透明,再从全透明变换成常规,就可以这样写:
- ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "alpha", 1f, 0f, 1f);
- animator.setDuration(5000);
- animator.start();
可以看到,我们还是调用了ofFloat()方法来去创建一个ObjectAnimator的实例,只不过ofFloat()方法当中接收的参数有点变化了。这里第一个参数要求传入一个object对象,我们想要对哪个对象进行动画操作就传入什么,这里我传入了一个textview。第二个参数是想要对该对象的哪个属性进行动画操作,由于我们想要改变TextView的不透明度,因此这里传入"alpha"。后面的参数就是不固定长度了,想要完成什么样的动画就传入什么值,这里传入的值就表示将TextView从常规变换成全透明,再从全透明变换成常规。之后调用setDuration()方法来设置动画的时长,然后调用start()方法启动动画
学会了这一个用法之后,其它的用法我们就可以举一反三了,那比如说我们想要将TextView进行一次360度的旋转,就可以这样写:
- ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "rotation", 0f, 360f);
- animator.setDuration(5000);
- animator.start();
那么如果想要将TextView先向左移出屏幕,然后再移动回来,就可以这样写:
- float curTranslationX = textview.getTranslationX();
- ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "translationX", curTranslationX, -500f, curTranslationX);
- animator.setDuration(5000);
- animator.start();
组合动画
实现组合动画功能主要需要借助AnimatorSet这个类,这个类提供了一个play()方法,如果我们向这个方法中传入一个Animator对象(ValueAnimator或ObjectAnimator)将会返回一个AnimatorSet.Builder的实例,AnimatorSet.Builder中包括以下四个方法:
- after(Animator anim) 将现有动画插入到传入的动画之后执行
- after(long delay) 将现有动画延迟指定毫秒后执行
- before(Animator anim) 将现有动画插入到传入的动画之前执行
- with(Animator anim) 将现有动画和传入的动画同时执行
好的,有了这四个方法,我们就可以完成组合动画的逻辑了,那么比如说我们想要让TextView先从屏幕外移动进屏幕,然后开始旋转360度,旋转的同时进行淡入淡出操作,就可以这样写:
- 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();
使用XML编写动画
如果想要使用XML来编写动画,首先要在res目录下面新建一个animator文件夹,所有属性动画的XML文件都应该存放在这个文件夹当中。然后在XML文件中我们一共可以使用如下三种标签:
- <animator> 对应代码中的ValueAnimator
- <objectAnimator> 对应代码中的ObjectAnimator
- <set> 对应代码中的AnimatorSet
那么比如说我们想要实现一个从0到100平滑过渡的动画,在XML当中就可以这样写:
- <animator xmlns:android="http://schemas.android.com/apk/res/android"
- android:valueFrom="0"
- android:valueTo="100"
- android:valueType="intType"/>
而如果我们想将一个视图的alpha属性从1变成0,就可以这样写:
- <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
- android:valueFrom="1"
- android:valueTo="0"
- android:valueType="floatType"
- android:propertyName="alpha"/>
其实XML编写动画在可读性方面还是挺高的,上面的内容相信不用我做解释大家也都看得懂吧。
另外,我们也可以使用XML来完成复杂的组合动画操作,比如将一个视图先从屏幕外移动进屏幕,然后开始旋转360度,旋转的同时进行淡入淡出操作,就可以这样写:
- <set xmlns:android="http://schemas.android.com/apk/res/android"
- android:ordering="sequentially" >
-
- <objectAnimator
- android:duration="2000"
- android:propertyName="translationX"
- android:valueFrom="-500"
- android:valueTo="0"
- android:valueType="floatType" >
- </objectAnimator>
-
- <set android:ordering="together" >
- <objectAnimator
- android:duration="3000"
- android:propertyName="rotation"
- android:valueFrom="0"
- android:valueTo="360"
- android:valueType="floatType" >
- </objectAnimator>
-
- <set android:ordering="sequentially" >
- <objectAnimator
- android:duration="1500"
- android:propertyName="alpha"
- android:valueFrom="1"
- android:valueTo="0"
- android:valueType="floatType" >
- </objectAnimator>
- <objectAnimator
- android:duration="1500"
- android:propertyName="alpha"
- android:valueFrom="0"
- android:valueTo="1"
- android:valueType="floatType" >
- </objectAnimator>
- </set>
- </set>
-
- </set>
最后XML文件是编写好了,那么我们如何在代码中把文件加载进来并将动画启动呢?只需调用如下代码即可:
- Animator animator = AnimatorInflater.loadAnimator(context, R.animator.anim_file);
- animator.setTarget(view);
- animator.start();