Android中的属性动画(Property Animation)——Android开发艺术探索笔记
Animator最早出现在Android 3.0 中,和之前的Animation框架相比,Animator更加的灵活并且具有更多的功能,官方推荐使用Animator代替Animation。在3.0之前可以使用nineoldandroids来实现相同的效果。
使用Animator前需要先了解几个概念:
Duration:动画播放时间 Time interpolation:属性值随着时间的改变情况,比如线性增长或者先快后慢 Repeat count:动画重复播放次数 Animator sets:动画集,可以使多个动画同时播放或者顺序播放 Frame refresh delay:动画每一帧的刷新时间,一般默认10ms刷新一次Property Animation
Property Animation非常强大,他可以让你几乎在任何东西上播放动画。Property Animation的结构如下图:
ValueAnimator用来跟踪动画运行的时间和属性的值。其中TimeInterpolator指定了动画的 interpolation,如AccelerateDecelerateInterpolator。TypeEvaluator指定属性的值如何计算比如IntEvaluator.
示例
点击一个Button,Button的宽和高分别增加到500dp和400dp。
Property Animation与View Animation的区别
View Animation只能对View添加动画 View Animation只能改变如scale、rotation等值,不能改变background color等属性 View Animation改变的只是View画的位置,并不是真正的View,比如一个button从左到右移动,触发onClick方法的位置还是初试的位置。 View Animation实现起来比Property Animation简单Evaluator
以IntEvaluator为例,源码如下:
public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
int startInt = startValue;
return (int)(startInt + fraction * (endValue - startInt));
}
很简单,就是根据初始值,结束值和当前时间与总时长的比例这三个值计算出当前某属性应该的值。
Animator
Animator提供了创建动画的基本结构,通常我们不直接使用它,而是使用它的子类。
ValueAnimator
使用ofInt(), ofFloat(), 或者 ofObject()方法来获得ValueAnimator实例
ValueAnimator animation = ValueAnimator.ofFloat(0f, 1f);
animation.setDuration(1000);
animation.start();
当然也可以自定义类型
ValueAnimator animation = ValueAnimator.ofObject(new MyTypeEvaluator(), startPropertyValue, endPropertyValue);
animation.setDuration(1000);
animation.start();
示例动画的源码
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final IntEvaluator mEvaluator = new IntEvaluator();
ValueAnimator valueAnimator = ValueAnimator.ofInt(1, 100);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
float fraction = valueAnimator.getAnimatedFraction();
button.getLayoutParams().width = mEvaluator.evaluate(fraction, button.getWidth(), 500);
button.getLayoutParams().height = mEvaluator.evaluate(fraction, button.getHeight(), 400);
button.requestLayout();
}
});
valueAnimator.setDuration(1000).start();
}
});
注:别忘了 button.requestLayout()和valueAnimator.setDuration(1000).start()。
ObjectAnimator
ObjectAnimator是ValueAnimator 的子类。可以直接对目标属性计算。
对foo这个对象的alpha属性做从0到1的变化,代码如下:
ObjectAnimator anim = ObjectAnimator.ofFloat(foo, "alpha", 0f, 1f);
anim.setDuration(1000);
anim.start();
为了使ObjectAnimator正常运行,还需要如下步骤:
要修改的属性必须有set方法,如setFoo() 如果你在values…参数中只指定了一个参数,默认为这是最后一个参数。参数必须有get方法,如getFoo() 有些属性需要手动刷新,所以要在onAnimationUpdate() 中调用invalidate()。如果没有要修改的属性必须有set方法,有如下三个解决办法:
如果有权限,添加set方法但是很多情况下我们是没有的… 使用这个类的wrapper class(包装类)
ObjectAnimator.ofFloat(wrapper, “alpha”, 0f, 1f),在这个包装类的setAlph中对原来View的alpha属性值进行更改 使用ValueAnimator
AnimatorSet
一个Set中包含多个动画,使用起来也很方便,直接上代码。
AnimatorSet bouncer = new AnimatorSet();
bouncer.play(bounceAnim).before(squashAnim1);
bouncer.play(squashAnim1).with(squashAnim2);
bouncer.play(squashAnim1).with(stretchAnim1);
bouncer.play(squashAnim1).with(stretchAnim2);
bouncer.play(bounceBackAnim).after(stretchAnim2);
ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f);
fadeAnim.setDuration(250);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(bouncer).before(fadeAnim);
animatorSet.start();
在XML中声明动画
新建res/animator/目录
每种Animator对应的标签
<code class="language-html hljs "><set android:ordering="sequentially"> <set> <cke:objectanimator android:propertyname="x" android:duration="500" android:valueto="400" android:valuetype="intType"> <cke:objectanimator android:propertyname="y" android:duration="500" android:valueto="300" android:valuetype="intType"> </cke:objectanimator></cke:objectanimator></set> <cke:objectanimator android:propertyname="alpha" android:duration="500" android:valueto="1f"> </cke:objectanimator></set></code>
在Activity中调用
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext,
R.anim.property_animator);
set.setTarget(myObject);
set.start();