Android动画详解之Android 动画属性和实现方法之属性动画(三)

属性动画
(一)、属性动画概念:
        属性动画,这个是在Android 3.0中才引进的。Property Animation故名思议就是通过动画的方式改变对象的属性.属性动画更改的是对象的实际属性,在View Animation(Tween Animation)中,其改变的是View的绘制效果,真正的View的属性保持不变。可以将属性动画理解为增强版的补间动画。
        比如无论如何缩放Button的大小,Button的有效点击区域还是没有应用动画时的区域,其位置与大小都不变。而在Property Animation中,改变的是对象的实际属性,如Button的缩放,Button的位置与大小属性值都改变了。
        Property Animation不止可以应用于View,还可以应用于任何对象。Property Animation只是表示一个值在一段时间内的改变,当值改变时要做什么事情完全是你自己决定的。


(二)为什么引入属性动画
Android3.0之前提供的补间动画机制还算相对比较健全的,比如你的需求中只需要对View进行移动、缩放、旋转和淡入淡出的操作,那么补间动画已经足够健全了。但是,如果一旦需求超出了这四种操作,补间动画就无能为力了。 
例如,我们需要改变View的宽度,这个时候就不能通过补间动画实现。此外,补间动画还有一个最大的缺陷,就是它只是改变了View的显示效果而已,并不会真正的改变View的属性。具体来说,例如屏幕左上角有一个Button,使用补间动画将其移动到右下角,此刻你去点击右下角的Button,它是绝对不会响应点击事件的,因此其作用区域依然还在左上角。只不过是补间动画将其绘制在右下角而已。
(三)、属性动画常用属性:
Duration动画的持续时间,默认300ms。android:duration属性(对应的xml文件)
Time interpolation:时间插值。LinearInterpolator、AccelerateDecelerateInterpolator,定义动画的变化率。android:interpolator属性
Repeat count and behavior:重复次数、以及重复模式;可以定义重复多少次;重复时从头开始(restart),还是反向(reverse)。android:repeatCount属性(可以是整数也可以是infinite(无限))android:repeatMode="restart"  
Animator sets: 动画集合,你可以定义一组动画,一起执行或者顺序执行。<set/>,该元素的android:ordering属性指定该组动画是按次序播放还是同时播放。有两个值(sequentially和together分别表示先后执行和同步执行)
Frame refresh delay:帧刷新延迟(帧刷新频率,每个多久播放一帧);默认为10ms,但最终依赖系统的当前状态。
(三)、属性动画API:相关的类
ObjectAnimator 动画的执行类(是ValueAnimator的子类,使用简单常用。少数场景下,由于其存在一些限制,再考虑使用ValueAnimator)
ValueAnimator 动画的执行类
AnimatorSet 用于控制一组动画的执行:线性,一起,每个动画的先后执行等。
AnimatorInflater 用户加载属性动画的xml文件
TypeEvaluator 类型估值,主要用于设置动画操作属性的值。
TimeInterpolator 时间插值
总的来说,属性动画就是,动画的执行类来设置动画操作的对象的属性、持续时间,开始和结束的属性值,时间差值等,然后系统会根据设置的参数动态的变化对象的属性。


ValueAnimator
ValueAnimator是整个属性动画机制当中最核心的一个类,前面我们已经提到了,属性动画的运行机制是通过不断地对值进行操作来实现的,而初始值和结束值之间的动画过渡就是由ValueAnimator这个类来负责计算的。它的内部使用一种时间循环的机制来计算值与值之间的动画过渡,我们只需要将初始值和结束值提供给ValueAnimator,并且告诉它动画所需运行的时长,那么ValueAnimator就会自动帮我们完成从初始值平滑地过渡到结束值这样的效果。除此之外,ValueAnimator还负责管理动画的播放次数、播放模式、以及对动画设置监听器等,确实是一个非常重要的类。




  ValueAnimator 常用方法:
  1、ofFloat()小数位的动画过渡
 2、ofInt()整数位的动画过度
 3、ofObject()
 4、setStartDelay()动画播放延迟时间
 5、setRepeatCount()动画循环次数
 6、setRepeatMode()循环模式:RESTART和REVERSE是重新播放和倒叙播放


valuseAnimator的使用比较简单,可以是一个单一的过渡,没有界面效果:

private void ValueTest(View view){
    //将值从0过度到1
    ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
    //可以设置多个这样就是从0到1再到0.5
    //ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f,0.5f);
    anim.setDuration(300);
    anim.start();
}
但是这样无法知道他是否是执行了,可以通过添加一个动画的监听器来监听他的回调,利用addUpdateListener()方法:
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        float currentValue = (float) animation.getAnimatedValue();
        Log.e("ceshi", "cuurent value is " + currentValue);
    }
});
将结果打印出来可以看到

ValueAnimator确实已经在正常工作了,值在300毫秒的时间内从0平滑过渡到了1。
也可以调用setStartDelay()设置动画延时播放的时间,和setRepeatCount()循环次数和setRepeatMode()循环模式

ObjectAnimator
相比于ValueAnimator,ObjectAnimator可能才是我们最常接触到的类,因为ValueAnimator只不过是对值进行了一个平滑的动画过渡,但我们实际使用到这种功能的场景好像并不多。而ObjectAnimator则就不同了,它是可以直接对任意对象的任意属性进行动画操作的,比如说View的alpha属性。
不过虽说ObjectAnimator会更加常用一些,但是它其实是继承自ValueAnimator的,底层的动画实现机制也是基于ValueAnimator来完成的,因此ValueAnimator仍然是整个属性动画当中最核心的一个类。那么既然是继承关系,说明ValueAnimator中可以使用的方法在ObjectAnimator中也是可以正常使用的,它们的用法也非常类似。
如果想将图片在3000毫秒内变成半透明再还原,可以这么写:

//它是可以直接对任意对象的任意属性进行动画操作的
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "alpha", 1f, 0f, 1f);
animator.setDuration(2000);
//设置循环次数
animator.setRepeatCount(2);
//设置循环方式
animator.setRepeatMode(ValueAnimator.RESTART);
animator.start();
这里ofFloat()内的参数中第一个需要传入一个object对象,就是需要动画实现的对象;
第二个参数是想对对象的那个属性进行动画操作;
第三个和以后的参数与ValueAnimator一致;
实现效果如下:


还可以按照一样的思路实现旋转缩放和移动
旋转代码:

//设置旋转
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "rotation", 0f,360f);
animator.setDuration(2000);
animator.start();
缩放代码:
//设置缩放
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "scaleX", 1.0f,0.5f,1.0f);
animator.setDuration(2000);
animator.start();
移动代码:
//设置移动
//获取图片当前位置
float initialX = myImageView.getTranslationX();
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "translationX", initialX,-200,initialX);
animator.setDuration(5000);
//设置动画插入器
animator.setInterpolator(new AccelerateInterpolator());
animator.start();
效果如下:


设置了动画插入器横向移动的时候先慢后快。
比较重要的是:
//ObjectAnimator.ofFloat第二个参数可以放置任意的值,其中(alpha、rotation、translationX、translationY和scaleY、scaleX这几个值,分别可以完成淡入淡出、旋转、水平或垂直移动、垂直或水平缩放缩放这几种动画)

组合动画
独立的动画能够实现的视觉效果毕竟是相当有限的,因此将多个动画组合到一起播放就显得尤为重要。幸运的是,Android团队在设计属性动画的时候也充分考虑到了组合动画的功能,因此提供了一套非常丰富的API来让我们将多个动画组合到一起。
实现组合动画功能主要需要借助AnimatorSet这个类,这个类提供了一个play()方法,如果我们向这个方法中传入一个Animator对象(ValueAnimator或ObjectAnimator)将会返回一个AnimatorSet.Builder的实例,AnimatorSet.Builder中包括以下四个方法:
after(Animator anim)   将现有动画插入到传入的动画之后执行
after(long delay)   将现有动画延迟指定毫秒后执行
before(Animator anim)   将现有动画插入到传入的动画之前执行
with(Animator anim)   将现有动画和传入的动画同时执行
先整体缩放再淡入淡出,效果如下:

代码实现:
1、利用AnimatorSet实现组合动画,这个是最丰富的可以实现动画前后顺序的处理
//利用AnimatorSet实现组合动画,这个是最丰富的可以实现动画前后顺序的处理
ObjectAnimator scaleXAnim = ObjectAnimator.ofFloat(view, "scaleX", 1f, 0.5f);
ObjectAnimator scaleYAnim = ObjectAnimator.ofFloat(view, "scaleY", 1f, 0.5f);
ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(view, "alpha", 1f, 0.5f);
AnimatorSet animSet = new AnimatorSet();
animSet.play(scaleXAnim).with(scaleYAnim).before(alphaAnim);
animSet.setDuration(3000);
animSet.start();
2、利用动画刷新监听实现组合动画,第二个参数随便写,只能一起执行
//利用动画刷新监听实现组合动画,第二个参数随便写,只能一起执行
ObjectAnimator anim = ObjectAnimator.ofFloat(view,"lw",1.0f,0.0f,1f);
anim.setDuration(5000);
anim.start();
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        float cVal = (Float) animation.getAnimatedValue();
        view.setAlpha(cVal);
        view.setScaleX(cVal);
        view.setScaleY(cVal);
    }
});
3、除了上面Animator类还可以使用PropertyValuesHolder类来实现组合动画,
 不过这个组合动画就没有上面的丰富了,使用PropertyValuesHolder类只能多个动画一起执行。
 当然我们得结合 ObjectAnimator.ofPropertyValuesHolder(Object target,PropertyValuesHolder… values);
 方法来使用。第一个参数是动画的目标对象,之后的参数是PropertyValuesHolder类的实例,可以有多个这样的实例。代码如下:
PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("alpha", 1f, 0f, 1f);
PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("scaleX", 1f, 0, 1f);
PropertyValuesHolder pvhZ = PropertyValuesHolder.ofFloat("scaleY", 1f, 0, 1f);
ObjectAnimator.ofPropertyValuesHolder(view, pvhX, pvhY, pvhZ).setDuration(5000).start();

Animator监听器
在很多时候,我们希望可以监听到动画的各种事件,比如动画何时开始,何时结束,然后在开始或者结束的时候去执行一些逻辑处理。这个功能是完全可以实现的,Animator类当中提供了一个addListener()方法,这个方法接收一个AnimatorListener,我们只需要去实现这个AnimatorListener就可以监听动画的各种事件了。
大家已经知道,ObjectAnimator是继承自ValueAnimator的,而ValueAnimator又是继承自Animator的,因此不管是ValueAnimator还是ObjectAnimator都是可以使用addListener()这个方法的。另外AnimatorSet也是继承自Animator的,因此addListener()这个方法算是个通用的方法。
添加一个监听器的代码如下所示:
private void AnimatorListener(View view){
    ObjectAnimator animator = ObjectAnimator.ofFloat(view, "rotation", 0f,360f);
    animator.setDuration(2000);
    //第一种监听方式
    animator.addListener(new Animator.AnimatorListener() {
        @Override
        public void onAnimationStart(Animator animator) {
            Log.e("ceshi", "Start");
        }

        @Override
        public void onAnimationEnd(Animator animator) {
            Log.e("ceshi",  "End");
        }

        @Override
        public void onAnimationCancel(Animator animator) {
            Log.e("ceshi", "Cancel");
        }

        @Override
        public void onAnimationRepeat(Animator animator) {
            Log.e("ceshi", "Repeat");
        }
    });
    animator.start();
    animator.setRepeatCount(2);
}
第二种监听方式,利用Android提供了一个适配器类,叫作AnimatorListenerAdapter实现动画的监听,代码如下:
//第二种方式,可以自定义加载监听事件,利用适配器
animator.addListener(new AnimatorListenerAdapter() {
    @Override
    public void onAnimationEnd(Animator animation) {
        super.onAnimationEnd(animation);
    }
});

可以自定义监听的方法,需要什么就写什么。
日志打印结果:


使用XML编写属性动画
通过XML来编写动画可能会比通过代码来编写动画要慢一些,但是在重用方面将会变得非常轻松,比如某个将通用的动画编写到XML里面,我们就可以在各个界面当中轻松去重用它。
如果想要使用XML来编写动画,首先要在res目录下面新建一个animator文件夹,所有属性动画的XML文件都应该存放在这个文件夹当中。然后在XML文件中我们一共可以使用如下三种标签:
<animator>  对应代码中的ValueAnimator
<objectAnimator>  对应代码中的ObjectAnimator
<set>  对应代码中的AnimatorSet
所有的都只需调用xml文件就好:
ObjectAnimator animator = (ObjectAnimator) AnimatorInflater.loadAnimator(getApplicationContext(),R.animator.object_animator);
animator.setTarget(view);
animator.start();
ValueAnimator:
valueFrom和valueTo分别是起始和终止的数值,valueType对应着ofFloat等;
<!--valueType对应着ofFloat ofInt ofObject-->
<animator xmlns:android="http://schemas.android.com/apk/res/android"
    android:valueFrom="0"
    android:valueTo="100"
    android:valueType="floatType"/>
ObjectAnimator:
其中propertyName是参数值可以是alpha也可以是scaleX等,跟java代码实现差不多
<objectAnimator android:valueFrom="1"
    android:valueTo="0.5"
    android:valueType="floatType"
    android:propertyName="alpha"
    xmlns:android="http://schemas.android.com/apk/res/android" />
组合动画:
ordering 有两个选项:sequentially 和 together 。其中 together 为默认项。
sequentially 表示 set 中的动画,按照先后顺序逐步进行(a 完成之后进行 b )。
together 表示set 中的动画,在同一时间同时进行。
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:ordering="sequentially" >
<!--ordering 有两个选项:sequentially 和 together 。其中 together 为默认项。
sequentially 表示 set 中的动画,按照先后顺序逐步进行(a 完成之后进行 b )。
together 表示set 中的动画,在同一时间同时进行。-->
    <objectAnimator
        android:duration="2000"
        android:propertyName="translationX"
        android:valueFrom="-200"
        android:valueTo="200"
        android:valueType="floatType" >
    </objectAnimator>

    <set android:ordering="together" >
        <objectAnimator
            android:duration="3000"
            android:propertyName="rotation"
            android:valueFrom="0"
            android:valueTo="360"
            android:valueType="floatType" >
        </objectAnimator>

        <set android:ordering="sequentially" >
            <objectAnimator
                android:duration="1500"
                android:propertyName="alpha"
                android:valueFrom="1"
                android:valueTo="0"
                android:valueType="floatType" >
            </objectAnimator>
            <objectAnimator
                android:duration="1500"
                android:propertyName="alpha"
                android:valueFrom="0"
                android:valueTo="1"
                android:valueType="floatType" >
            </objectAnimator>
        </set>
    </set>

</set>


效果与java代码相同。


参考了大神的博客:http://blog.csdn.net/guolin_blog/article/details/43536355




源码: 下载




评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值