[置顶] Android动画学习之属性动画(Property Animator)-1、基础用法

经过前两章的学习,终于到了我们使用最多的属性动画了。属性动画是Android3.0(API 11)中引入的新的动画机制,相较于补间动画,它除了可以实现补间动画的所有效果外,还能实现补间动画无法做到的效果,比如我们现在要求一张图片背景色渐变,补间动画就无法完成,而使用属性动画就可以很简单的实现这个效果。另外补间动画只能作用在View上,而不能作用于非View的对象上,比如我们自定义一个View,此View的位置我们由Ponit类(包含x、y轴坐标信息),我们要求使用动画改变View的位置,就需要使用动画操作point对象,那么就只能使用属性动画来完成。对于补间动画来说,我们之前就已经讲过了,动画只会改变View的绘制位置而不会改变其真正属性,所以像触摸事件不会跟随动画移动,就会出现view平移后点击事件仍然留在原地的尴尬事情,而我们要介绍的属性动画就没有这个问题,因为是直接操作的View的属性,因此在其移动后,相应的事件也会随之移动。

属性动画中我们使用较多的两个类,一个是ValueAnimator,另一个是ObjectAnimator,其中后者继承前者,并且封装了许多常用操作,因此比前者更加易用。ValueAnimator的父类则是Animator,Animator还有一个常用子类是AnimatorSet(动画集合),这个我们也会在后面介绍。

ok,讲了这么多废话,都不如代码直观,下面我们就来讲解ValueAnimator、ObjectAnimator以及AnimatorSet的简单使用:

ValueAnimator

先上用法:

alphaValueAnimator = ValueAnimator.ofFloat(1.0f,0f);
alphaValueAnimator.setDuration(1000);
alphaValueAnimator.setRepeatCount(1);
alphaValueAnimator.setRepeatMode(ValueAnimator.REVERSE);
alphaValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
    ivContainer.setAlpha((float)animation.getAnimatedValue());
    }
    });

我们这里写了一个渐隐渐现的动画,动画透明度从1变到0,再从0变到1,然后结束。可以看到使用方法里和补间动画有很多相似的地方,例如设置动画时间(setDuration)、设置重复次数(setRepeatCount)、设置重复模式(setRepeatMode)等等。其中ValueAnimator的of…方法中,前者是动画初始值,后者是动画结束值,你也可以传多个参数,例如:

ValueAnimator.ofFloat(1.0f,0.5f,1f,0f);

就带便透明度从1变化为0.5再变化为1再变化为0的动画。

ValueAnimator支持的其他常用方法还有ofInt()、ofArgb()、ofObject()、ofPropertyValueHolder(),前两个方法使用和ofFloat大致类似,后两个方法我们留在后面在分析属性动画执行流程时会进行讲解。

需要注意的是addUpdateListenr方法,这个方法为动画执行加了坚听,我们可以在onAnimationUpdate方法中对我们要执行动画的对象进行更改。如果想观察动画执行过程的,可以在onAnimationUpdate方法中打印animation.getAnimatedValue的值查看变化过程,可以对ValueAnimator加深理解,我在这里就不再演示。如果我们用到了其他效果,可以相应在onAnimationUpdate方法中写下对应逻辑。用法比较简单,不多说。

下面是我们使用ValueAnimator实现的动画效果,如图:

ObjectAnimator

ObjectAnimator的使用就比上面的要简单的多,写法是这样的:

float translationX = ivContainer.getTranslationX();
translateObjectAnimator = ObjectAnimator.ofFloat(ivContainer,"translationY",translationX,translationX-200);
translateObjectAnimator.setRepeatCount(1);
translateObjectAnimator.setRepeatMode(ValueAnimator.REVERSE);
translateObjectAnimator.setDuration(1000);

上面的效果是将ImageView向上平移200像素再平移回原位置(如果不设置repeatCount则平移后会留在原位置,这里为了方便演示设置了1个重复次数并且设置重复方式为反转)。可以看出ObjectAnimator的使用要比他的父类简单许多,ofFloat方法中,第一个参数Target接受一个Object对象,这是动画执行的对象,第二个参数propertyName是动画执行过程选中要改变的对象中的值,注意这个属性名在响应的对象里必须有setter和getter方法,其余参数则是动画执行的初始值和结束值,其余与ValueAnimator类似。

我们在对view添加动画的时候,可以使用的PropertyName都有哪些,常用的有“translationY”、”rotation”、”tranlationX”、”alpha”、”scale”等等。

使用ObjectAnimator我们就不必再添加动画监听来设置给目标对象,在调用start()方法后内部会自动进行调用,后续我们会进行详细的分析。

执行效果如下图:

AnimatorSet(动画集合)

AnimatorSet也是继承于Animator,主要用于组合动画如同时播放两个动画,或者之后播放,提前播放动画、延迟播放等等,主要用到的方法有:

play(Animator anim)    //播放当前动画
after(Animator anim)   //将该动画插入原动画之前
after(long delay)    //将动画延迟相应毫秒
before(Animator anim)   //将该动画放入原动画
with(Animator anim)    //将该动画与原动画同时播放

上述方法返回的都是Animator.Builder对象,有了这些方法,我们对view进行组合操作如下:

animatorValueSet = new AnimatorSet();
animatorValueSet.play(alphaValueAnimator)
    .with(rotateValueAnimator)
    .before(scaleValueAnimator)
    .after(translateValueAnimator);

可以看到,该动画会先执行translateValueAnimator,然后同时执行alphaValueAnimator和rotateValueAnimator,最后执行scaleValueAnimator。

下面是分别使用ValueAnimator和ObjectAnimator来使用集合动画(其实没什么卵区别):

监听动画开始与结束

有时我们会有在动画结束或开始时执行某些方法的需求,这时候需要我们对动画进行监听。上面我们已经用过了监听动画状态更新的监听器,另外还有addListener和addPauseListener,分别监听动画的开始结束等状态和停止状态。

animatorObjectSet.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {
                //动画开始时调用
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                //动画结束时调用
            }

            @Override
            public void onAnimationCancel(Animator animation) {
                //动画取消时调用
            }

            @Override
            public void onAnimationRepeat(Animator animation) {
                //动画重复执行时调用
            }
        });

我们可以在几个方法中来进行逻辑操作,有时候我们并不想监听这么多状态,那么就可以使用AnimatorListenerAdapter这个抽象类,该类实现了AnimatorListener和AnimatorPauseListener,我们可以按照自己需要来复写相应方法:

animatorObjectSet.addListener(new AnimatorListenerAdapter() {
        });

xml编写属性动画

我们知道,补间动画可以有两种形式来实现,一种是xml形式,另一种是代码形式。属性动画我们刚刚讲了代码的实现形式,那么它可不可以写进xml中呢,答案是肯定的。

属性动画所在的目录是res/animator下,如果res下没有animator,可以新建该目录,新建xml文件,其中我们可以使用的根节点有这么三个:

  • 相当于代码中的ValueAnimator
  • 相当于ObjectAnimator
  • 相当于AnimatorSet

我这里实现的效果是这样的:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:ordering="sequentially">
    <objectAnimator
        android:duration="1000"
        android:repeatCount="1"
        android:valueType="floatType"
        android:valueFrom="0"
        android:valueTo="-200"
        android:repeatMode="reverse"
        android:propertyName="translationY"/>
    <set android:ordering="together">
        <objectAnimator
            android:duration="1000"
            android:repeatCount="1"
            android:valueType="floatType"
            android:valueFrom="1.0"
            android:valueTo="0"
            android:repeatMode="reverse"
            android:propertyName="alpha"/>


        <objectAnimator
            android:duration="1000"
            android:repeatCount="1"
            android:valueType="floatType"
            android:valueFrom="0"
            android:valueTo="-180"
            android:repeatMode="reverse"
            android:propertyName="rotation"/>
    </set>

    <objectAnimator
        android:duration="1000"
        android:repeatCount="1"
        android:valueType="floatType"
        android:valueFrom="1"
        android:valueTo="1.5"
        android:repeatMode="reverse"
        android:propertyName="scaleY"/>
</set>

实现的效果和Java代码一样,需要注意set的属性ordering,together为同时执行,sequentially为顺序执行。

在程序中调用这个动画的方法是:

/**
 * xml实现动画
 */
protected void xmlAnimatorTest (View view) {
    Animator animator = AnimatorInflater.loadAnimator(this,R.animator.animator_test);
    animator.setTarget(ivContainer);
    animator.start();
}

实现的效果如图所示:

ok,到这里属性动画的基本用法就讲完了,接下来将会介绍Animator的底层实现和一些高级用法以及酷炫的动画特效,代码地址依然是:github,欢迎查看。

也欢迎来我的博客来探讨相关技术~

enjoy~

猜你喜欢

转载自blog.csdn.net/xiaomi987/article/details/79972691