Android 动画之属性动画 - 基本使用

本文详细介绍了Android属性动画的基本使用,包括动画特征、常见类如ValueAnimator和ObjectAnimator,以及插值器和监听器的运用。通过实例展示了如何使用ofFloat/ofInt/ofArgb/ofObject方法实现不同类型的动画效果,并探讨了ObjectAnimator的局限性。此外,还讨论了AnimatorUpdateListener和AnimatorListener在动画监听中的作用。

Android动画系列:

介绍

Android之补间动画详解已经了解到,View Animation通过重绘View的视图的方式来完成View的动画效果,但View对象本身没有改变。在Android 3.0(API 11),对View添加了新属性和相应的get()和set(),通过在调用set方法设置属性时,其属性更改时会自动调用invalidate()方法来刷新屏幕。

view用拥有set()方法的属性列表:

属性描述
translationX / translationY/ translationZ这两个属性控制了View所处的位置,它们的值是由layout容器设置的,是相对于坐标原点(0,0左上角)的一个偏移量。translationX和 translationY表示水平方向,translationZ为垂直方向(API 21新添加)
rotation,rotationX和rotationY控制View绕着轴点(pivotX和pivotY)旋转
scaleX和scaleY控制View基于pivotX和pivotY的缩放。
pivotX和pivotY旋转的轴点和缩放的基准点,默认是View的中心点
x / y / Z用于在其容器中描述视图的最终位置,作为左值和顶值以及translationX和translationY值的和。z为view的高度属性
alpha表示view的透明度。默认情况下,此值为1(不透明),值为0表示完全透明(不可见)

属性动画可以通过更改View的属性,重绘View,更改属性后自动调用invalidate()方法来刷新屏幕,以完成动画效果。

动画特征

  1. Duration:动画执行时间,默认时间为300 ms
  2. TimeInterpolator :时间插值,用于计算指定属性的值在当前动画的执行时间
  3. Repeat count and behavior:重复次数、以及重复模式;可以定义重复多少次;重复时从头开始,还是反向。
  4. Animator Sets:动画集合,可以定义一起播放或顺序播放或在指定延迟后播放,
  5. Frame refresh delay:帧刷新延迟,对于定义的动画,多久刷新一次帧;默认为10ms,但最终依赖系统的当前状态及系统底层定时器所提供的服务。

相关类

  1. ValueAnimator:值动画执行类,常配合AnimatorUpdateListener使用
  2. ObjectAnimator:对象动画执行类。
  3. TimeInterpolator:定义动画插值器
  4. TypeEvaluator:类型估值,用于设置复杂的动画操作属性的值
  5. PropertyValuesHolder : 属性存储器,为两个执行类提供更新多个属性的功能
  6. Keyframe :为 PropertyValuesHolder提供多个关键帧的操作值
  7. AnimatorSet :一组动画的执行集合类:设置执行的先后顺序,时间等
  8. AnimatorUpdateListener :动画更新监听
  9. AnimatorListener :动画执行监听,在动画开始、重复、结束、取消时进行回调。
  10. AnimatorInflater :加载属性动画的xml文件。

常见的插值器

Interpolator对象资源ID功能作用
AccelerateDecelerateInterpolator@android:animaccelerate_decelerate_interpolator先加速再减速
AccelerateInterpolator@android:anim/accelerate_interpolator加速
AnticipateInterpolator@android:anim/anticipate_interpolator先回退一小步然后加速前进
AnticipateOvershootInterpolator@android:anim/anticipate_overshoot_interpolator在上一个基础上超出终点一小步再回到终点
BounceInterpolator@android:anim/bounce_interpolator最后阶段弹球效果
CycleInterpolator@android:anim/cycle_interpolator周期运动
LinearInterpolator@android:anim/linear_interpolator匀速运动

ValueAnimator

常量

  1. INFINITE:此值用于setRepeatCount(int)属性,用于无限期地重复动画。实际上其值等于-1,在XML中定义动画无限重复时,通常设置android:repeatCount=”-1”,也就是这样了
  2. RESTART:当动画设置为无限重复或者执行次数大于1时,动画执行结束后,从头开始
  3. REVERSE:当动画设置为无限重复或者执行次数大于1时,动画执行结束后,动画反向执行

常用API

返回值方法注解
voidaddUpdateListener(ValueAnimator.AnimatorUpdateListener)添加动画更新监听
voidcancel()取消当前执行的动画
voidend()结束当前动画
voidpause()暂停动画
voidreverse()反向执行动画
voidstart()开始动画
voidresume()恢复暂停的动画,从暂停的位置开始动画
floatgetAnimatedFraction()获取当前动画的执行进度
ObjectgetAnimatedValue()获取当前属性值
ObjectgetAnimatedValue(String)通过属性标签获取属性的当前值
booleanisRunning()判断动画是否在执行(动画已开始且运行时间超过所设置的延迟时间,但动画未结束)
booleanisStarted()判断动画是否已经开始而且动画未结束
static ValueAnimatorofArgb(int… values)设置颜色值之间切换的动画(比如设置背景颜色)
static ValueAnimatorofFloat(float… values)设置在浮点值之间的动画(比如移动)
static ValueAnimatorofInt(int… values)设置在整数值之间的动画
static ValueAnimatorofObject(TypeEvaluator evaluator, Object… values))在values值之间的动画
static ValueAnimatorofPropertyValuesHolder(PropertyValuesHolder… values)设置在PropertyValuesHolders之间执行动画

注:

1.getAnimatedValue()和getAnimatedFraction()的区别

getAnimatedValue()的返回值是一个Object,表示当仅有一个属性处于动画状态时,由该ValueAnimator计算的当前属性值。

getAnimatedFraction()的返回值是一个float,其值在0.0和1.0之间,其线性度是由插值器决定的(fraction = t / duration ),而animatedValue值是由相关属性值 * fraction所得的。

2.ValueAnimator的构造函数其实就是一个默认构造函数,并包含动画相关”属性”信息,若采用此种方式创建实例,需通过调用setXX(…)方法设置动画相关属性。当然此时你可以通过静态方法创建ValueAnimator实例,比如ValueAnimator valueAnimator = ValueAnimator.ofFloat(0.0f, 1.0f),此ValueAnimator设置了相关的动画”属性”

public class ValueAnimator() {
    ***
    public ValueAnimator() {
    }
    ***
}

Evaluators

类(接口)描述
IntEvaluator用于计算int属性的值的默认计算器
FloatEvaluator用于计算float属性的值的默认计算器
ArgbEvaluator用于计算表示为十六进制值的颜色属性值的默认计算器
TypeEvaluator用于自定义属性值的计算器

3.动画的执行动作解析

  • cancel():取消当前执行的动画,将属性值分配成动画的当前值,调用cancel()方法后,会先触发AnimatorListener的onAnimationCancel方法的执行,然后触发onAnimationEnd方法的执行。
  • end():结束当前动画,直接从当前状态跳转到最终的完成状态,将属性值分配成动画的终止值,并触发动画监听器AnimatorListener的onAnimationEnd方法的执行。
  • pause():暂停当前执行的动画,将属性值分配成动画的当前值。(API > 19)
  • reverse():反向执行动画,但其执行动画的位置为动画的当前位置。但,若动画停留在起始位置,动画将从最后一帧开始;若动画停留在最后一帧,动画将从第一帧开始执行动画。
  • start():从第一帧开始执行动画。若设置了动画延迟,动画不会立即执行,待延迟时间过后,动画再执行;若未设置动画延迟,动画会立即执行
  • resume():恢复暂停的动画,从暂停的位置开始动画(API > 19)

动画实例

ofFloat/ofInt

ofFloat(float…)方法接收一系列的float类型的值,其内部使用了FloatEvaluator。通过该方法ValueAnimator可以对float值进行动画渐变。现通过ValueAnimator.ofFloat(0.0f, 400f);创建了一个初始值为0.0f,结束值为400f的动画。通过addUpdateListener(ValueAnimator.AnimatorUpdateListener)添加动画监听,AnimatorUpdateListener有一个onAnimationUpdate方法,ValueAnimator会每隔一定时间(默认间隔10ms)计算属性的值,每当计算的时候就会回调onAnimationUpdate方法。在该方法中,我们通过调用ValueAnimator的getAnimatedValue()方法获取到当前动画计算出的属性值,然后我们将该值传入btnProperty的setTranslationX()、setTranslationY()方法中,从而更新了btnProperty的位置,以达到了移动btnProperty的目的。

    // 通过静态方法构建一个ValueAnimator对象
    // 设置数值集合
    mValueAnimator = ValueAnimator.ofFloat(0.0f, 400f);
    // 设置作用对象
    mValueAnimator.setTarget(btnProperty);
    // 设置动画无限循环
    mValueAnimator.setRepeatCount(ValueAnimator.INFINITE);
    // 设置动画执行时间
    mValueAnimator.setDuration(4000);
    // 添加动画更新监听
    mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            // 获取当前值
            Float mValue = (Float)animation.getAnimatedValue();
            // 动画进度(t/duration)
            float fraction = animation.getAnimatedFraction();

            Log.d("PropertyActivity", "mValue:" + mValue);
            Log.d("PropertyActivity", "fraction:" + fraction + " | t:" + fraction * animation.getDuration());

            // 设置横向偏移量
            btnProperty.setTranslationX(mValue * 0.5f);
            // 设置纵向偏移量
            btnProperty.setTranslationY(mValue);
        }
    });
    // 开始执行动画
    mValueAnimator.start();

这里写图片描述

ofInt(Int…)的使用方法与ofFloat()类似,这个可以自行解决,练练手~

ofArgb

此方法要求最低SDK 版本为21,是新添的方法,用于构造颜色值变化的动画。其内部使用了ArgbEvaluator,可以用该方法实现将一个颜色动画渐变到另一个颜色,我们从中可以不断获取中间动画产生的颜色值。我们知道一个int值包含四个字节,在Android中第一个字节代表Alpha分量,第二个字节代表Red分量,第三个字节代表Green分量,第四个字节代表Blue分量,且我们常用16进制表示颜色,这样看起来更明显易懂一些,比如int值0xffff0000表示的红色,0xff00ff00表示的是绿色,最前面的ff表示的是Alpha。ofArgb方法会通过ArgbEvaluator将颜色拆分成四个分量,然后分别对各个分量进行动画计算,然后将四个计算完的分量再重新组合成一个表示颜色的int值,这就是ofArgb方法的工作原理。

现通过静态方法ofArgb(Int…args)创建ValueAnimator对象,设置动画的执行时间为4000ms,设置动画的循环次数为无限循环。在AnimatorUpdateListener监听中,将ArgbEvaluator计算出的颜色的值,通过setBackgroundColor(int)传给btn,设置btn的背景颜色。

    //起始颜色为红色
    int startColor = 0xffff0000;
    //终止颜色为绿色
    int endColor = 0xff00ff00;

    // 通过静态方法构建一个ValueAnimator对象
    // 设置数值集合
    mValueAnimator = ValueAnimator.ofArgb(startColor, endColor);
    // 设置作用对象
    mValueAnimator.setTarget(btnProperty);
    // 设置动画无限循环
    mValueAnimator.setRepeatCount(ValueAnimator.INFINITE);
    // 设置动画执行时间
    mValueAnimator.setDuration(4000);
    // 添加动画更新监听
    mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            int valueColor = (int) animation.getAnimatedValue();
            Log.d("PropertyActivity", "mValue:" + valueColor);
            btnProperty.setBackgroundColor(valueColor);
        }
    });

这里写图片描述

ofObject

ofObject(TypeEvaluator, Object… values)与ofInt()、ofFloat()并不相同,其不仅有动画属性值作为参数,同时必须传入动画的属性计算器。一方面,由于ofObject()传入的属性值类型不能够确定,从而不能够确定哪种类型的属性值计算器。另一方面,官方提供的动画属性值就那么几种,并不能够满足我们实际的需求,假如传入了一个自定义类或者一系列的String属性值,官方提供的动画属性就不能满足了。而ofInt()、ofFloat()中动画的属性值类型固定,在其内分别内置了IntEvaluaor、FloatEvaluator。既然是这样,不管是使用官方提供的Evaluator还是Valuator都必须指定TypeEvaluator。

具体实例不在写出,详见

ObjectAnimator

介绍

ObjectAnimator是ValueAnimator的子类,不同于ValueAnimator的是,其内置了属性值计算器以及拥有对View的命名属性(拥有getter()和setter()的属性)。此时,不必在添加ValueAnimator.AnimatorUpdateListener,ObjectAnimator会自动设置View的属性并自动更新。

实例化的ObjectAnimator类似于ValueAnimator,可以指定对象、对象属性的名称及属性值之间的动画。

ObjectAnimator anim = ObjectAnimator.ofFloat(btn, "alpha", 0f, 1f);
anim.setDuration(1000);
anim.start();

局限性

由于ObjectAnimator只能自动更新View的命名属性,有一定的局限性。使用ObjectAnimator时应注意:

  1. ObjectAnimator在动画期间自动更新属性,其必须能够调用setter()方法,因而View的动画属性必须有setter()方法。例如当设置View的背景色时,其不是命名属性,此时你只能

    • 自定义View,将此属性设置为命名属性
    • 改用ValueAnimator,添加AnimatorUpdateListener监听,在回调方法内设置View属性
  2. ObjectAnimator的属性值参数有且仅有一个,假定此值为结束值,该View必须有getter()方法,以用来获取初始值,而且getter()方法必须是get()的形式。

  3. 动画的属性的getter()和setter()方法中,propertyName的类型必须与ObjectAnimator指定的开始值和结束值的类型一致。

代码实例

ObjectAnimator//  
     .ofFloat(view, "rotationX", 0.0F, 360.0F)//  
     .setDuration(500)//  
     .start();  

动画监听

AnimatorUpdateListener

AnimatorUpdateListener是ValueAnimator类的一个成员内部类,其是静态的,且仅声明了一个方法onAnimationUpdate(ValueAnimator)。在动画执行过程中,每次更新都会调用该方法,可以在该回调中手动更新view的属性。

public class ValueAnimator{

    *** 

     public static interface AnimatorUpdateListener {

        void onAnimationUpdate(ValueAnimator animation);

    }

    ****
}

注:动画执行时,ValueAnimator会计算相关动画且执行动画,但其并不会设置view的属性和对view进行重绘。此时需设置AnimatorUpdateListener监听,并在onAnimationUpdate回调中执行View的invalidate()方法。

Animator.AnimatorListener

对于动画执行过程中,在动画执行过程中,我们总是想执行这样那样的操作,比如在动画结束时,不再显示当前框架,此时我们就得对整个动画的执行进行监听,了解当前动画的执行进度。如果想监听动画,需调用addListener(listener)添加Animator.AnimatorListener。

Animator.AnimatorListener内声明的监听回调方法:

  • onAnimationStart(Animator animation):动画开始时回调
  • onAnimationCancel(Animator animation):调用cancel()方法手动取消动画时回调
  • onAnimationEnd(Animator animation):调用end()方法手动结束动画或者动画正常结束时回调
  • onAnimationRepeat(Animator animation):动画重复时回调

    ValueAnimator mValueAnimator = ValueAnimator.ofFloat(0f, 400f);
    // 设置作用对象
    mValueAnimator.setTarget(btnProperty);
    // 设置动画无限循环
    mValueAnimator.setRepeatCount(ValueAnimator.INFINITE);
    // 设置动画执行时间
    mValueAnimator.setDuration(4000);
    mValueAnimator.addListener(new Animator.AnimatorListener() {
    
        public void onAnimationStart(Animator animation) {
            Log.d("PropertyActivity", "动画开始");
        }
    
        @Override
        public void onAnimationEnd(Animator animation) {
            Log.d("PropertyActivity", "动画结束");
        }
    
        @Override
        public void onAnimationCancel(Animator animation) {
            Log.d("PropertyActivity", "动画取消");
        }
    
        @Override
        public void onAnimationRepeat(Animator animation) {
            Log.d("PropertyActivity", "动画重复");
        }
    });
    mValueAnimator.start();
    

这样就可以监听动画的开始、结束、被取消、重复等事件,但是有时候我们只需监听其中的某一个事件,比如动画的结束,此时可以添加AnimatorListenerAdapter,取代AnimatorListener。

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

从AnimatorListenerAdapter源码中可以清晰的看出,AnimatorListenerAdapter是一个抽象类,其实现了Animator.AnimatorListener和Animator.AnimatorPauseListener两个接口,并对接口中的方法空实现。通过添加AnimatorListenerAdapter来监听动画时,没有必要在实现接口的中的方法,只要选择你需要的那个回调并重写即可。

public abstract class AnimatorListenerAdapter implements Animator.AnimatorListener,
        Animator.AnimatorPauseListener {

    public void onAnimationCancel(Animator animation) {
    }

    public void onAnimationEnd(Animator animation) {
    }

    public void onAnimationRepeat(Animator animation) {
    }

    public void onAnimationStart(Animator animation) {
    }

    public void onAnimationPause(Animator animation) {
    }

    public void onAnimationResume(Animator animation) {
    }
}

Animator.AnimatorPauseListener

Animator.AnimatorPauseListener用于监听动画暂停时的场景,其与pause()、resume()方法一起在API 19新增的API,也就是说添加此监听,SDK版本应在19以上才可以使用。

Animator.AnimatorPauseListener内声明的监听回调方法:

onAnimationPause(Animator animation):动画暂停时回调(调用pause()方法)
onAnimationResume(Animator animation):之前动画暂停,动画回复时回调(调用resume())

mValueAnimator.addPauseListener(new Animator.AnimatorPauseListener() {
    @Override
    public void onAnimationPause(Animator animation) {
        Log.d("PropertyActivity", "动画暂停");
    }

    @Override
    public void onAnimationResume(Animator animation) {
        Log.d("PropertyActivity", "动画暂停");
    }
});

参考资料

  1. Android 属性动画(Property Animation) 完全解析 (上)
  2. Android 属性动画(Property Animation) 完全解析 (下)
  3. Android属性动画
  4. 官方文档-Property Animation
  5. 深入理解 Android 动画 Interpolator 类的使用
  6. 浅析Android动画(三),自定义Interpolator与TypeEvaluator
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值