动画系列之属性动画

一、简介

前面总结了视图动画的使用,下面来说说属性动画。
属性动画是API1(Android 3.0)才加入的动画。我们都知道视图动画不能真正的改变对象的属性,并不能满足我们的需求,此时属性动画就诞生了,而属性动画就是很好的对对象进行扩展,通过对对象的属性进行反射来实现动画。
优点:可以对任何对象进行动画。
缺点:

  1. 在API11之间无法使用, 只能借助第三方插件(nineoldandroids)。
  2. 由于是通过反射来实现的,所以必须提供属性的setter()方法, 如果需要获取初值,还需要提供getter()方法。

二、相关属性介绍

<set>  -----> AnimatorSet
android : ordering 表示集合中动画播放顺序  together : 同时播放 sequentially : 按照前后顺序播放

<animator> ----> ValueAnimator
android : duration  动画时间
android : valueFrom  动画开始值
android : valueTo  动画结束值
android : startOffset  动画的延迟时间 即多长时间后开始动画
android : repeatCount  动画重复的次数 默认值为0  -1 表示无限循环
android : repeatMode 表示动画重复的方式 restart 每次都是重新开始 reverse 表示逆向重复
android : valueType 表示android : propertyName 所指定属性的类型  intType floatType

<objectAnimator>----> ObjectAnimator 是ValueAnimator的子类
其他属性和<animator> 相同
android : propertyName 表示动画作用的属性名称
注意:如果propertyName  所指定的属性表示的是颜色, 则不需要指定valueType  类型, 系统会自动对颜色进行处理。

三、属性动画的实现

1. ObjectAnimator 的实现

ValueAnimatior的实现和ObjectAnimator实现类似, 就不举例。

 a、 xml形式实现

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:propertyName="rotation"
android:repeatCount="1"
android:repeatMode="reverse"
android:valueFrom="0"
android:valueTo="360"
android:valueType="floatType" />
代码中引用
ObjectAnimator animator = (ObjectAnimator) loadAnimator(this, R.animator.object_animator);
animator.setTarget(iv_anim);
animator.start();

b、纯Java代码实现

ObjectAnimator animator = ObjectAnimator.ofFloat(iv_anim, "translationY", 100f, 300f);
animator.setDuration(3000);
animator.start();

2、组合动画的实现

a、xml形式实现

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:ordering="sequentially">
    <set>
        <set android:ordering="sequentially">
            <objectAnimator
                android:duration="200"
                android:propertyName="translationX"
                android:repeatMode="reverse"
                android:valueFrom="0"
                android:valueTo="200" />
            <objectAnimator
                android:duration="200"
                android:propertyName="translationX"
                android:repeatMode="reverse"
                android:valueFrom="200"
                android:valueTo="0" />
        </set>
    </set>
    <set >
        <objectAnimator
            android:duration="400"
            android:propertyName="rotation"
            android:repeatMode="reverse"
            android:valueFrom="0"
            android:valueTo="360" />
        <set android:ordering="sequentially">
            <objectAnimator
                android:duration="200"
                android:propertyName="translationX"
                android:repeatMode="reverse"
                android:valueFrom="0"
                android:valueTo="-200" />
            <objectAnimator
                android:duration="200"
                android:propertyName="translationX"
                android:repeatMode="reverse"
                android:valueFrom="-200"
                android:valueTo="0" />
        </set>
    </set>
</set>
代码中引用

AnimatorSet animator = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.property_animator);
animator.setTarget(iv_anim);
animator.start();

b、纯Java代码实现

ObjectAnimator animator0 = ObjectAnimator.ofFloat(iv_anim, "alpha", 0.5F, 1F);
ObjectAnimator animator1 = ObjectAnimator.ofFloat(iv_anim, "translationY", 200F, 0);
ObjectAnimator animator2 = ObjectAnimator.ofFloat(iv_anim, "translationX", -200F, 0);
AnimatorSet set = new AnimatorSet();
set.setDuration(3000);
set.setInterpolator(new BounceInterpolator());
set.playTogether(animator0, animator1, animator2);
set.start();

注意:此处是使用playTogether()方法让所用动画同事执行的,如果我们想让动画按照一定的顺序执行,可以调用play()方法来获取 AnimatorSet.Builder 实例,AnimatorSet.Builder 给我们提供了一下方法,用于控制动画执行 。

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

c、通过PropertyValuesHolder实现

PropertyValuesHolder translationX = PropertyValuesHolder.ofFloat("translationX", 100, 300);
PropertyValuesHolder translationY = PropertyValuesHolder.ofFloat("translationY", 200, 400);
ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(iv_anim, translationX, translationY);
objectAnimator.setDuration(500);
objectAnimator.start();
d、通过ViewPropertyAnimator实现
ViewPropertyAnimator animate = iv_anim.animate();
animate.scaleX(1.0f).scaleXBy(0.5f).scaleY(1.0f).scaleXBy(0.5f).setDuration(300).start();
多属性动画,专作用于View组件,能够实现的动画相对单一,只能实现比如缩放,透明度改变,平移、旋转等,具体函数名字:平移 translationX,translationY, X,Y,缩放 scaleX,scaleY, 旋转 rotationX, rotationY,透明度 alpha。

四、动画的监听

有时在动画开始或者结束的时候,需要做些其他操作,这是我们就需要借助于接口监听了,主要用两个回调接口。

1、AnimotorListener : 属性动画的状态监听 (开始 结束 取消 重复)

 set.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {
                Log.i(TAG, "onAnimationStart: ------动画开始的时候回调 ");
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                Log.i(TAG, "onAnimationStart: ------动画结束的时候回调 ");
            }

            @Override
            public void onAnimationCancel(Animator animation) {
                Log.i(TAG, "onAnimationStart: ------动画取消的时候回调 ");
            }

            @Override
            public void onAnimationRepeat(Animator animation) {
                Log.i(TAG, "onAnimationStart: ------动画重复的时候回调 ");
            } 
        });
当然,有时候我们并不需要接口中的所用方法, 有没有办法实现需要哪个实现哪个呢?办法当然是有的, Android给我们提供了这样一个抽象类 AnimatorListenerAdater(public abstract class AnimatorListenerAdapter implements Animator.AnimatorListener,Animator.AnimatorPauseListener), 在进行接口监听的时候,创建这个抽象类的匿名对象,就可以实现需要哪个方法就重写哪个方法啦。

 set.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationCancel(Animator animation) {
                super.onAnimationCancel(animation);
                
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
            }

            @Override
            public void onAnimationRepeat(Animator animation) {
                super.onAnimationRepeat(animation);
            }

            @Override
            public void onAnimationStart(Animator animation) {
                super.onAnimationStart(animation);
            }

            @Override
            public void onAnimationPause(Animator animation) {
                super.onAnimationPause(animation);
            }

            @Override
            public void onAnimationResume(Animator animation) {
                super.onAnimationResume(animation);
            }
        });

2、AnimatorUpdataListener  属性动画更新的监听  会监听整个动画的全过程, 属性动画每播放一帧动画 onAnimationUpdate()就会被调用一次。

 animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                //可以手动的修改动画的值
            }
        });

五、使用小技巧:

在实际开发中,最好使用代码实现的方式来实现属性动画,因为:

  1. 代码实现方式简单 。
  2. 在很多情况下 属性的起始值是无法确定的,需要通过代码动态实现。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值