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方法中的参数就是时间的百分比,返回值为属性值改变的百分比
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)); } }