Android动画的使用(二):属性动画

属性动画(Property Animation)是Android 3.0出现的动画,它将动画逻辑从view中抽离了出来,抽象化程度更高。上一篇讲的是补间动画,其动画渲染是实际的位置是不变的,就像幻影一样,而属性动画是真实的位置改变。看名字我们就可以猜测它是对view的属性(x,y,alpha等)进行改变从而实现动画。属性动画主要包括两个关键类:ValueAnimator和ObjectAnimator。

1.使用ValueAnimator实现动画

ValueAnimator的常用构造方法

ValueAnimator通过ValueAnimator.ofFloat(float …value)进行构造,可以有多个参数。动画的运行就是按照参数的变化而变化,中间值使用插值器插值(Interpolator),构造后还可以设置其他属性,例如:


        ValueAnimator an = ValueAnimator.ofFloat(0,360);
        an.setDuration(2000);
        an.setRepeatCount(ValueAnimator.INFINITE);//或-1,一直循环
        an.setRepeatMode(ValueAnimator.RESTART);
        an.setInterpolator(new LinearInterpolator());
        an.start();

将ValueAnimator设置构造完成后,就需要监听里面数字的变化的,给ValueAnimator加入dUpdateListener监听器

    an.addUpdateListener(new AnimatorUpdateListener() {

            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                /*这里可以做你想做的事,如setROtation,setAlpha等,只要view有set<属性>的方法都可以,另外我们还可以在view自定义set方法。*/
                view.setRotation((Float)animation.getAnimatedValue());
            }
        });

通过监听ValueAnimator的值变化,控制view的属性变化(如:setRotation()),这样就实现了动画的操作了。

使用xml构造ValueAnimator


<animator xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="2000"
    android:interpolator="@android:anim/linear_interpolator"
    android:repeatCount="-1"
    android:repeatMode="reverse"
    android:valueFrom="0"
    android:valueTo="360"
    android:valueType="floatType" >

animator>

读取xml资源定义的动画

ValueAnimator an = (ValueAnimator) AnimatorInflater.loadAnimator(this,R.anim.value_animation);
        an.start();
        an.addUpdateListener(new AnimatorUpdateListener() {

            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                Log.d("tag", "值:"+(Float)animation.getAnimatedValue());
            }
        });

ValueAnimator的ofObject构造方法和TypeEvaluator

ValueAnimator还可以使用ofObject(evaluator, values)的构造方法,此时就需要实现TypeEvaluator接口了。
这个接口了可以实现除了系统提供的类型如float(开始时我们就是使用float构造)之外的类型的变化。类似于c++的重载运算符。例如定义person A怎么变成person B的。我们先看看之前使用的offFloat构造时使用的TypeEvaluator是怎么样的。下面是android源码。

public class FloatEvaluator implements TypeEvaluator<Number> {

    public Float evaluate(float fraction, Number startValue, Number endValue) {
        float startFloat = startValue.floatValue();
        return startFloat + fraction * (endValue.floatValue() - startFloat);
    }
}

可以看到float类型的变换是startFloat + fraction * (endValue - startFloat);fraction为动画进行的百分比。现在我们来定义person A变成person B,我们就假设A变老了就成B了,即年龄变化即可。实现如下:

public class PersonEvaluator implements TypeEvaluator<Person>{

    @Override
    public Person evaluate(float fraction, Person startValue, Person endValue) {
        int startAge = startValue.getAge();
        Person p = new Person(startValue);
        int r = (int) (startAge+fraction*(endValue.getAge()-startAge));
        p.setAge(r);
        return p;
    }

}

这样我们就可以使用offOject的构造方法了,这时候UpdateListener回调AnimatedValue就是一个person了。

        Person A = new Person(11);
        Person B = new Person(22);
        ValueAnimator personAnim = ValueAnimator.ofObject(new PersonEvaluator(), A,B);
        personAnim.addUpdateListener(new AnimatorUpdateListener() {

            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                Person p = (Person) animation.getAnimatedValue();
                Log.d("tag", "年龄:"+p.getAge());
            }
        });

如果将Person变成是图片,那不就是成了帧动画了吗?具体用途还是看各位想象了。

2.使用ViewPropertyAnimator实现动画

这个是用起来最方便的动画了,我觉得。

//透明度1-0变化的动画
tvhello = (TextView) findViewById(R.id.hello);
tvhello.animate().alpha(1).alpha(0).setDuration(2000);      

一行代码搞掂。(不过这种需要android 3.1以上才能使用)

3.使用ObjectAnimator实现动画

ObjectAnimator的常用构造方法

ObjectAnimator是继承于ValueAnimator的类,因此上面介绍valueAnimator有的东西它都有,比如TypeEvaluator的自定义。它主要实现的是查找传出对象的setter方法,在UpdateListener上调用,这样我们就不需要自己去监听UpdateListener了。


tvhello = (TextView) findViewById(R.id.hello);
ObjectAnimator anim0 = ObjectAnimator.ofFloat(tvhello, "alpha", 1f,0f,1f);
anim0.start();

也很简单,两行搞掂。这里实现的是透明度从1f->0f—>1f;”alpha”对应于view中的setAlpha 方法。其他的例如setTranslationX就写成”translationX”。只有有setter方法都可以用。(即使没有setter的方法我们也可以自定
义view加上哦,满足驼峰式命名就行)。

ObjectAnimator的ofObject构造方法

ObjectAnimator中输出TypeEvaluator参数。这里写的是颜色的变化,Person换成了点poin.

//[自定义view参数] poin,这里自定义view需要定义setPoin(Poin p);方法。
ObjectAnimator an = ObjectAnimator.ofObject(myview, "poin",new ColorEvalutor(),new Poin(),new Poin());

ObjectAnimator的ofPropertyValuesHolder构造方法

使用PropertyValuesHolder实现多个属性一起变化。

PropertyValuesHolder holder1 = PropertyValuesHolder.ofFloat("alpha", 0f,1f);
PropertyValuesHolder holder2 = PropertyValuesHolder.ofFloat("rotetion", 1f,180f);
//holder的个数不限       
ObjectAnimator.ofPropertyValuesHolder(tvhello, holder1,holder2).setDuration(2000).start();

4.组合动画

定义多个ObjectAnimator,然后使用AnimatorSet串起来。

ObjectAnimator anim0 = ObjectAnimator.ofFloat(tvhello, "alpha", 1f,0f,1f);
        ObjectAnimator anim1 = ObjectAnimator.ofFloat(tvhello, "translationX", tvhello.getTranslationX(),-500,100);
        ObjectAnimator anim2 = ObjectAnimator.ofFloat(tvhello, "rotation", 0,180,0);
        AnimatorSet animset = new AnimatorSet();
        animset.play(anim0).after(anim1).with(anim2);
        animset.setDuration(2000);

        animset.start();

AnimatorSet使用的是建造者模式,animset.play(anim0)返回一个build,然后就可以设置我们的组合动画了。也可以这样写

animset.play(anim0).with(anim1)
animset.play(anim1).before(anim2)
animset.play(anim3).after(anim2)

此时是anim0和anim1一起播放,anim2在anim1播放之后播放,anim3在anim2播放之后播放。可能比较难理解。这就像我们平时排队一样,谁在谁左边一样,注意不能前后矛盾哦。给这动画排队就是 [(anim0,anim1)、anim2、anim3] 你再对照一下是不是满足了。还有解析一下animset.play(anim0).after(anim1).with(anim2);这都是以anim0为基准进行描述的,排队循序:anim1、(anim0,anim2).

5.xml定义动画

对xml构造ValueAnimator扩展到所有属性动画。


<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:ordering="sequentially" >

    <objectAnimator
        android:duration="1000"
        android:propertyName="scaleY"
        android:valueFrom="1"
        android:valueTo="5"
        android:valueType="floatType" />

    <set android:ordering="together" >
        <objectAnimator
            android:duration="1000"
            android:propertyName="rotationX"
            android:valueFrom="10"
            android:valueTo="1"
            android:valueType="floatType" />
        <objectAnimator
            android:duration="1000"
            android:propertyName="alpha"
            android:valueFrom="0"
            android:valueTo="0.5"
            android:valueType="floatType" />
    set>

set>
        Animator anim = AnimatorInflater.loadAnimator(this, R.animator.set_simple);
        anim.setInterpolator(new DecelerateInterpolator(2f));//设置变化规律,如:先快后慢。可自定义
        anim.setTarget(tvhello);
        anim.start();

6.对属性动画进行监听

属性动画有一个AnimatorListener接口,而如果我们只需要监听部分事件,只需要使用它的实现类AnimatorListenerAdapter,然后重写相关方法就行了。

anim.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                Log.d("tag", "动画结束了");
            }
        });

7.给属性动画添加插值器Interpolator

Interpolator是补间动画上就有的,而属性动画在此基础上加了TimeInterpolator,它可以控制动画的速率(先快后慢,加快,变慢等)上一篇有介绍:Android动画的使用(一):补间动画与逐帧动画,这里主要讲如何写自己的插值器Interpolator

public interface TimeInterpolator {
    float getInterpolation(float input);
}

只有一个方法,这样我们就可以实现自己的插值器了。
先看使用Android提供的插值器

Animator anim = AnimatorInflater.loadAnimator(this, R.animator.set_simple);//xml定义的属性动画
anim.setInterpolator(new DecelerateInterpolator(2f));//设置变化规律,如:先快后慢。可自定义

直接setInterpolator就可以使用了。OK,我们来实现自己的插值器。

public class MyInterpolator implements TimeInterpolator{

    @Override
    public float getInterpolation(float input) {
        //input是时间百分比,取值范围是(0-1)

        //return input;匀速就是直接返回了。
        return input*input;
    }

}

我们直接平方,这就是二次函数,0-1之间就是开始是慢后面加快了。

//使用自己的插值器
anim.setInterpolator(new MyInterpolator());

你可能感兴趣的:(Android开发,动画,android)