前面几篇说完view动画和帧动画,这篇来说一下属性动画
首先来说一下属性动画和view动画的对比:
View动画的缺点:
1)只有基本的四种变化(旋转、平移、缩放、透明度)
2)经过变化的view在新位置上不能触发点击事件
propertyAnimation是API 11引进来的,如果想在API 11以前的版本使用,需要加入Nineoldandroids库来兼容以前的版本,相比于view动画优点是:
1)只要对象有属性,就能实现其动画效果(要求:该属性得有set和get(可选)方法)
2)在android3.0以后的版本上在view变化后的新位置上点击能触发点击事件
当然了propertyAnimation不但可以在xml中定义也可以用java代码来实现
在xml文件中,在res/animator下新建xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<!-- ordering有两个值,together是子动画同时播放
sequentially是按顺序播放 -->
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:ordering="together" >
<!-- animator:对应于ValueAnimator
objectAnimator与animator属性都差不多,
但objectAnimator多了一个propertyName用来设置对象的属性-->
<animator
android:duration="500"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:repeatCount="infinite"
android:repeatMode="restart"
android:startOffset="100"
android:valueFrom="100.0"
android:valueTo="200.0"
android:valueType="floatType" >
</animator>
<objectAnimator
android:propertyName="x" >
</objectAnimator>
</set>
使用上面的xml文件,如下:
Animator animator = AnimatorInflater.loadAnimator(this, R.anim.pre_in);
animator.setTarget(view);
animator.start();
使用java代码:
ObjectAnimator:
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "x", 100f, 200f);
animator.setDuration(500);
animator.setInterpolator(new AccelerateDecelerateInterpolator());
animator.setEvaluator(new IntEvaluator());
animator.start();
ValueAnimator:
ValueAnimator animator = ValueAnimator.ofFloat(100f, 200f);
animator.setDuration(500);
animator.setInterpolator(new AccelerateDecelerateInterpolator());
animator.setEvaluator(new IntEvaluator());
animator.setTarget(view);
animator.start();
animator.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
view.setX((Float) animation.getAnimatedValue());
}
});
valueAnimator比ObjectAnimator多几行代码,但是灵活性比较高
在ValueAnimator中使用了AnimationUpdateListener这个类,用于监听整个动画过程,动画是由许多帧构成的,每播放一帧就会调用onAnimationUpdate()方法,通过这个特点来进行对属性值得改变。
AnimatorSet:
ValueAnimator animator_01 = ValueAnimator.ofFloat(100f, 200f);
animator_01.setDuration(500);
animator_01.setInterpolator(new AccelerateDecelerateInterpolator());
animator_01.setEvaluator(new IntEvaluator());
animator_01.setTarget(view);
animator_01.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
view.setX((Float) animation.getAnimatedValue());
}
});
ValueAnimator animator_02 = ValueAnimator.ofFloat(100f, 200f);
animator_02.setDuration(500);
animator_02.setInterpolator(new AccelerateDecelerateInterpolator());
animator_02.setEvaluator(new IntEvaluator());
animator_02.setTarget(view);
animator_02.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
view.setY((Float) animation.getAnimatedValue());
}
});
AnimatorSet animSet = new AnimatorSet();
animSet.playTogether(animator_02, animator_01);// animator_02和animator_01同时播放
//animSet.play(animator_01).after(animator_02); 先animator_01后animator_02
//animSet.play(animator_01).before(animator_02); 先animator_02后animator_01
animSet.start();
说完动画,再看看插值器(Interpolator)和估值器(Evaluator):
插值器:根据时间流逝的百分比来计算出当前属性改变的百分比
估值器:根据当前属性改变的百分比来计算出当前属性的值
插值器我们可以自己定义,只要实现TimeInterpolator即可:
先来看一下TimeInterpolator源码
package android.animation;
public interface TimeInterpolator {
/**
* Maps a value representing the elapsed fraction of an animation to a value that represents
* the interpolated fraction. This interpolated value is then multiplied by the change in
* value of an animation to derive the animated value at the current elapsed animation time.
*
* @param input A value between 0 and 1.0 indicating our current point
* in the animation where 0 represents the start and 1.0 represents
* the end
* @return The interpolation value. This value can be more than 1.0 for
* interpolators which overshoot their targets, or less than 0 for
* interpolators that undershoot their targets.
*/
float getInterpolation(float input);
}
就是一个接口,实现该接口即可:
public class MyInterpolator implements Interpolator{
@Override
public float getInterpolation(float input) {
return input;
}
}
getInterpolationgetInterpolationgetInterpolationgetInterpolation方法中的参数就是时间的百分比,返回值为属性值改变的百分比
多个效果组成一个动画除了AnimatorSet外,还可以:
1)通过一个属性值的改变,在onAnimationUpdate中对view进行设置,但是耦合性比较高
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(view, "abc", 0.0f,1.0f);
objectAnimator.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
view.setScaleX((Float) animation.getAnimatedValue());
view.setAlpha((Float) animation.getAnimatedValue());
}
});
2)通过PropertyValuesHolder来实现
PropertyValuesHolder holder01 = PropertyValuesHolder.ofFloat("x",50f, 200f);
PropertyValuesHolder holder02 = PropertyValuesHolder.ofFloat("alpha", 0.0f, 1.0f);
ValueAnimator valueAnimator = ValueAnimator.ofPropertyValuesHolder(holder01,holder02);
valueAnimator.start();
再来看一下估值器:
package android.animation;
public interface TypeEvaluator<T> {
public T evaluate(float fraction, T startValue, T endValue);
}
只需实现 TypeEvaluator<T>接口即可:
public class MyEvaluator implements TypeEvaluator<Float> {
/**
* fraction:属性改变的百分比
* startValue:开始值
* endValue:结束值
*/
@Override
public Float evaluate(float fraction, Float startValue, Float endValue) {
float startInt = startValue;
return (float) (startInt + fraction * (endValue - startValue));
}
}