Android属性动画Property Animation系列二之ObjectAnimator

转载请注明出处 http://blog.csdn.net/feiduclear_up/article/details/45915377

前面一篇博客解读了Android属性动画Property Animation系列一之ValueAnimator的相关知识点以及怎么使用。这篇博客继续解读Android 属性动画 ObjectAnimator 类的使用。

ObjectAnimator

相比ValueAnimator类,ObjectAnimator更加实用,因为它真正可以作用在一个对象上。不过ObjectAnimator是继承自ValueAnimator的,所以主体方法还是ValueAnimator里实现的。那么我们来看看ObjectAnimator的使用吧。常用方法有这些:ofFloat(),ofInt(),ofObject(),ofArgb(),ofPropertyValuesHolder()。

ObjectAnimator使用

平移

ObjectAnimator animator = ObjectAnimator.ofFloat(imageView, "translationX", 0.0f, 350.0f, 0f);
        animator.setDuration(2500).start();

ofFloat()方法的第一个参数表示动画操作的对象(可以是任意对象),第二个参数表示操作对象的属性名字(只要是对象有的属性都可以),第三个参数之后就是动画过渡值。当然过度值可以有一个到N个,如果是一个值的话默认这个值是动画过渡值的结束值。如果有N个值,动画就在这N个值之间过渡。

缩放

 ObjectAnimator animator = ObjectAnimator.ofFloat(imageView, "scaleX", 1.0f, 1.5f);
        animator.setDuration(2000).start();

旋转动画

ObjectAnimator animator = ObjectAnimator.ofFloat(imageView, "rotationX", 0.0f, 90.0f,0.0F);
        animator.setDuration(2000).start();

透明度动画

ObjectAnimator animator = ObjectAnimator.ofFloat(imageView, "alpha", 1.0f, 0.3f, 1.0F);
        animator.setDuration(2000);//动画时间

是不是感觉很简单?两行代码就能实现一个动画效果,当然只是一个简单的动画配置,如果你需要更加好的效果动画,你可以通过这些方法去配置:

  1. setInterpolator():设置动画插值
  2. setDuration():设置动画执行时间
  3. setRepeatCount():设置动画重复次数
  4. setRepeatMode():设置动画重复模式
  5. setStartDelay():设置动画延时操作
  6. setTarget():设置动画的对象
  7. setEvaluator():设置动画过度的评估者。

详细动画配置如下:

 ObjectAnimator animator = ObjectAnimator.ofFloat(imageView, "alpha", 1.0f, 0.3f, 1.0F);
        animator.setDuration(2000);//动画时间
        animator.setInterpolator(new BounceInterpolator());//动画插值
        animator.setRepeatCount(-1);//设置动画重复次数
        animator.setRepeatMode(ValueAnimator.RESTART);//动画重复模式
        animator.setStartDelay(1000);//动画延时执行
        animator.start();//启动动画

可以根据自己的需求进行配置调整。

组合动画

上面我们看到的都是单个动画,那么需要实现组合动画怎么办呢?不着急,Android工程师给我们提供了两种方法来实现,AnimatorSet类,ObjectAnimator.ofPropertyValuesHolder()方法。

组合动画1–AnimatorSet的使用

这个类提供了一个play()方法,如果我们向这个方法中传入一个Animator对象(ValueAnimator或ObjectAnimator)将会返回一个AnimatorSet.Builder的实例,AnimatorSet.Builder中包括以下四个方法:

after(Animator anim) 将现有动画插入到传入的动画之后执行
after(long delay) 将现有动画延迟指定毫秒后执行
before(Animator anim) 将现有动画插入到传入的动画之前执行
with(Animator anim) 将现有动画和传入的动画同时执行

好的,有了这些方法,我们来实现一个组合动画:开始图片的透明度从不透明到0.2的透明再到不透明,随着整个布局背景的颜色变化的同时ImageView先向右平移200个像素,然后再放大2倍,最后沿着X轴从0到90度再到0度的旋转。

代码如下:

 ObjectAnimator animator = ObjectAnimator.ofInt(container, "backgroundColor", 0xFFFF0000, 0xFFFF00FF);
        ObjectAnimator animator1 = ObjectAnimator.ofFloat(imageView, "translationX", 0.0f, 200.0f, 0f);
        ObjectAnimator animator2 = ObjectAnimator.ofFloat(imageView, "scaleX", 1.0f, 2.0f);
        ObjectAnimator animator3 = ObjectAnimator.ofFloat(imageView, "rotationX", 0.0f, 90.0f, 0.0F);
        ObjectAnimator animator4 = ObjectAnimator.ofFloat(imageView, "alpha", 1.0f, 0.2f, 1.0F);

        //组合动画方式1
        AnimatorSet set = new AnimatorSet();
        ((set.play(animator).with(animator1).before(animator2)).before(animator3)).after(animator4);
        set.setDuration(5000);
        set.start();

我们可以看到,先创建了5个ObjectAnimator的动画,然后 new 了一个AnimatorSet对象,将刚才5个动画play到AnimatorSet对象中执行。执行效果就是上面的效果图了。
当然你要可以使用AnimatorSet类中的playTogether(Animator… items)方法实现多个动画同时执行的效果。

组合动画2–PropertyValuesHolder的使用

除了上面Animator类还可以使用PropertyValuesHolder类来实现组合动画,不过这个组合动画就没有上面的丰富了,使用PropertyValuesHolder类只能多个动画一起执行。当然我们得结合 ObjectAnimator.ofPropertyValuesHolder(Object target,
PropertyValuesHolder… values);方法来使用。第一个参数是动画的目标对象,之后的参数是PropertyValuesHolder类的实例,可以有多个这样的实例。代码如下:

 //组合动画方式2
        PropertyValuesHolder valuesHolder = PropertyValuesHolder.ofFloat("translationX", 0.0f, 300.0f);
        PropertyValuesHolder valuesHolder1 = PropertyValuesHolder.ofFloat("scaleX", 1.0f, 1.5f);
        PropertyValuesHolder valuesHolder2 = PropertyValuesHolder.ofFloat("rotationX", 0.0f, 90.0f, 0.0F);
        PropertyValuesHolder valuesHolder3 = PropertyValuesHolder.ofFloat("alpha", 1.0f, 0.3f, 1.0F);

        ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(imageView, valuesHolder, valuesHolder1, valuesHolder2, valuesHolder3);
        objectAnimator.setDuration(2000).start();

同样,我们也是先创建了4个PropertyValuesHolder类的动画,然后通过ObjectAnimator.ofPropertyValuesHolder()方法将执行动画的对象和4个动画组合起来,返回的对象是ObjectAnimator,然后我们就可以通过 ObjectAnimator对象中的 start()方法来启动这个动画了。PropertyValuesHolder类除了ofInt,ofFloat,还有ofObject,ofKeyframe方法。我们来看看ofKeyframe(String propertyName, Keyframe… values)第一个参数属性名称,第二个参数Keyframe对象。那么看看Keyframe对象吧

Keyframe的使用

这个类是通过控制time/value键值对来实现动画效果的。Keyframe类里面实现的 ofInt,ofFloat,ofObject方法。来看看ofFloat(float fraction, float value)第一个参数表示动画完成度,值在0—1之间变化。第二个参数表示当前帧动画的值。还不明白那就来点简单粗暴的吧。动画向右平移200个像素之后又移动回原来位置的动画

ObjectAnimator animator1 = ObjectAnimator.ofFloat(imageView, "translationX", 0.0f, 200.0f, 0f);

我们利用Keyframe来实现如上动画效果

Keyframe keyframe1 = Keyframe.ofFloat(0f, 0f);//第一帧动画 动画完成度0的时候的值是0
        Keyframe keyframe2 = Keyframe.ofFloat(.5f, 200.0f);//第二帧动画 动画完成度0.5也就是一半的时候值是200
        Keyframe keyframe3 = Keyframe.ofFloat(1f, 0f);//第三帧动画 动画完成度1也就是动画结束的时候值是0.

        PropertyValuesHolder property = PropertyValuesHolder.ofKeyframe("translationX", keyframe1, keyframe2, keyframe3);
        ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(imageView, property);

以上代码通过三帧动画值的过渡来实现 平移动画的效果。

我们是不是有这么一个疑惑—属性动画是通过改变对象的属性值来达到一个动画效果。那么这个对象的属性名称可以是什么呢?答案是:任何一切带有set开头的方法属性名字。可能我们常用的有:

  1. 平移 translationX,translationY, X,Y。
  2. 缩放 scaleX,scaleY。
  3. 旋转 rotationX, rotationY。
  4. 透明度 alpha。

    也就是说我们所有控件都有以上setTranslationX(),setScaleX(),setRotationX(),setAlpha()等方法。
    我们不仅限于这几个属性,就拿TextView控件来说,只要是TextView有的属性都可以用来实现动画效果,比如 字体大小:“textColor”,字体颜色“textSize”等。

ViewPropertyAnimator

该类是多属性动画,从名字就可以看出该类的作用对象是view,当一个view对象需要同时执行多个属性动画的时候就可以考虑使用该类了。比如说:一个ImageView先右移动的同时进行放大一倍的动画效果实现如下:

ViewPropertyAnimator animator5 = imageView.animate();
        animator5.translationX(200).scaleX(2).setDuration(2000).start();

注意:使用ViewPropertyAnimator类需要API>=12。通过调用animate()方法返回ViewPropertyAnimator对象,然后通过对于属性方法设置动画的最终效果值就可以实现多属性动画啦!是不是很简单?突然感觉利用这个类实现多动画比AnimatorSet方便多了,自然动画对象限制为View。

动画监听器

很多时候我们可能要在某一个动画执行之前 或者动画结束之后进行一些其他的操作,比如:动画结束之后进行网络数据请求等。那么我们就需要去获得该动画的一些状态,幸好,android系统给我们提供了一个动画监听器接口,来监听不同状态下的动画情况。实现也很简单,只要调用addListener(AnimatorListener listener)方法给动画添加监听器就好了,然后实现AnimatorListener接口即可。代码如下:

animator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {
                //TODO 动画开始前的操作
                /** * 比如这里可以初始化一些UI */
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                //TODO 动画结束的操作
                /** * 比如这里可以等动画结束进行一些账号登录或者网络数据请求等。 */
            }

            @Override
            public void onAnimationCancel(Animator animation) {
                //TODO 动画取消的操作
            }

            @Override
            public void onAnimationRepeat(Animator animation) {
                //TODO 动画重复的操作
            }
        });

可以根据不同需求来实现接口里面的四个方法。有时候你会觉得我不需要监听动画的四种状态,我只需要监听动画结束时候的状态,如果使用上面的方法就会感觉代码臃肿了,不过没关系,Android系统给我们提供了一个更好用的方法

animator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                //TODO 动画结束的操作
                /** * 比如这里可以等动画结束进行一些账号登录或者网络数据请求等。 */
            }
        });

可以看出,我们使用了AnimatorListenerAdapter 动画接口适配器代替AnimatorListener接口。其实AnimatorListenerAdapter的源码只是一个实现了AnimatorListener接口的抽象类而已,你需要监听哪种动画状态就重写哪种方法就可以了。是不是觉得这个方法很nice~?如果你仅仅满足于这个那就OUT了,Android系统还给我们提供了一个更加精确的方法来时刻监听当前动画的执行情况。那就是addUpdateListener(AnimatorUpdateListener listener)方法了。调用该方法只需实现AnimatorUpdateListener接口就可以读取到动画的每个更新值了。来看看代码:

animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float value = (float) animation.getAnimatedValue();
                //可以根据自己的需要来获取动画更新值。
                Log.e("TAG", "the animation value is " + value);
            }
        });

这个方法具体用在哪些地方可以参看上一节Android属性动画Property Animation系列一之ValueAnimator的动态的画一条斜线动画实现。

使用XML编写动画

除了代码实现以上所有的动画,跟补间动画一样,Android系统也提供xml来实现属性动画。
相对于代码实现动画,xml可能显得麻烦些,不过xml动画可重复性好,编写一个xml动画可以多次使用。那么就来看看xml实现动画吧。和补间动画不同的是,在res目录下新建一个animator目录,补间动画是新建anim目录。在xml中实现动画会使用到如下三个标签

  • 对应代码中的ValueAnimator
  • 对应代码中的ObjectAnimator
  • 对于代码中的Animator

比如实现一个0–10的值的平滑过渡动画xml代码如下:

<?xml version="1.0" encoding="utf-8"?>
<animator xmlns:android="http://schemas.android.com/apk/res/android" android:valueFrom="0" android:valueTo="10" android:duration="2000" android:valueType="intType"></animator>

在比如实现一个从0旋转到90度的动画xml代码如下:

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:duration="2000" android:propertyName="rotationX" android:valueFrom="0" android:valueTo="90" android:valueType="floatType" />

我们来个组合动画吧。

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" android:duration="2000" android:ordering="sequentially"><!--动画执行顺序 sequentially:顺序执行;together:同时执行。 -->

    <objectAnimator  android:propertyName="translationX" android:valueFrom="0" android:valueTo="200" android:valueType="floatType" />

    <set android:ordering="together">
        <objectAnimator  android:propertyName="scaleX" android:valueFrom="1" android:valueTo="2" android:valueType="floatType" />
        <objectAnimator  android:propertyName="rotationX" android:valueFrom="0" android:valueTo="90" android:valueType="floatType" /><!--动画值的类型-->

    </set>


</set>

xml动画写好了,接下来看看怎么在代码中调用它吧:

Animator animator = AnimatorInflater.loadAnimator(context, R.animator.anim_file); 
animator.setTarget(view); 
animator.start(); 

通过AnimatorInflater.loadAnimator方法加载xml动画返回一个Animator的对象,然后调用setTarget方法给动画设置对象调用哪个start启动动画即可完成xml动画效果啦。是不是也很简单呢?最后发现xml的动画可读性还是挺高的,点个赞~。

下一节我们继续学习 LayoutTransition:布局动画

你可能感兴趣的:(动画,animation,属性,property)