Android属性动画(一)—— 属性动画的基本使用

版权声明:本文为博主原创文章,转载请注明出处: https://blog.csdn.net/qq_38182125/article/details/89598061

一、概述

属性动画(property animation)是在 API11 引入的新特性,它相比于补间动画有如下优势:

  • 补间动画只能对View进行操作,而属性动画可以对任何对象进行操作,甚至还可以没有对象。
  • 补间动画只能实现平移、缩放、旋转和透明度这4种动画,当我们需要更多效果时,补间动画无能为力;而属性动画则具有良好的扩展性,只要我们根据一定的规则,我们可以操作多种属性。
  • 补间动画只改变View的显示而不真正改变View的属性;而属性动画直接操作的就是属性值,所以不存在此类问题。

本篇文章介绍的是属性动画的简单使用,结构如下:

  • ValueAnimator的使用
  • ObjectAnimator的使用
  • AnimatorSet的使用
  • ViewPropertyAnimator的使用
  • 为属性动画设置监听

二、ValueAnimator

ValueAnimator是属性动画中最为核心的一个类,属性动画之所以叫做属性动画是因为它改变的是对象的属性值,所以属性动画的运行机制就是通过不断地对值进行修改来达到动画的效果。

ValueAnimator正是用于做这类计算的,它接收动画的开始值和结束值,然后利用内部的计时引擎不断地修改值,从初始值过渡到结束值。它有如下3个比较重要的方法用于创建ValueAnimator对象:

方法 描述
ValueAnimator.ofInt(int… values) 将初始值以整型数值的形式过渡到结束值
ValueAnimator.ofFloat(float… values) 将初始值以浮点型数值的形式过度到结束值
ValueAnimator.ofObject(TypeEvaluator evaluator, Object… values) 将初始值以对象的形式过渡到结束值

在本部分我们会先介绍ofIntofFloatofObject在估值器部分进行介绍,接下来我们看到ValueAnimator中的常用方法:

方法 描述
setDuration 设置动画时长,单位为ms
setStartDelay 设置开始的延迟时间,单位为ms
setRepeatCount 设置重复次数,默认为0。取值为INFINITE表示无限重读
setRepeatMode 设置重复模式,有两种取值:RESTART和REVERSE
setEvaluator 设置估值器
addUpdateListener 添加值更新监听器,每当值更新时都会回调此方法
start 开启动画
pause 暂停动画
cancel 关闭动画

接下来通过一个简单的例子来展示ValueAnimator的使用:

ValueAnimator anim = ValueAnimator.ofFloat(0.0f, 100.0f);
anim.setDuration(500);
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        Log.d(TAG, "current value is " + animation.getAnimatedValue());
    }
});
anim.start();

输出结果:

D/MainActivity: current value is 0.0
D/MainActivity: current value is 9.549156
D/MainActivity: current value is 74.909256
D/MainActivity: current value is 83.06559
D/MainActivity: current value is 86.875656
D/MainActivity: current value is 90.078354
D/MainActivity: current value is 93.037094
D/MainActivity: current value is 95.5053
D/MainActivity: current value is 97.35491
D/MainActivity: current value is 98.795845
D/MainActivity: current value is 99.680565
D/MainActivity: current value is 99.996056
D/MainActivity: current value is 100.0

本例中我们采用ofFloat来初始化ValueAnimator,然后将初始值和结束值设置为0和100,时长为500ms。添加监听的原因是我们没有将改值应用与任何View上,无法直观看到变化,所以通过打印Log的方式查看值的变化。如果我们想要采用整型值,如下所示:

ValueAnimator anim = ValueAnimator.ofInt(0, 100);
anim.setDuration(500);
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        Log.d(TAG, "current value is " + animation.getAnimatedValue());
    }
});
anim.start();

只需改变第一行代码,我们的Log中打印出来的就全为整型值了。以上就是关于ValueAnimator的简单使用,接下来我们看到ObjectAnimator的使用。


三、ObjectAnimator

ObjectAnimatorValueAnimator的子类,相比于ValueAnimator只能对值进行过渡,ObjectAnimator则可以直接对任意对象的属性值进行动画操作,所以在平常开发中我们使用的更多的是ObjectAnimator。而它创建对象的方式和 ValueAnimator 非常类似,提供了下列三个方法:

public static ObjectAnimator ofInt(Object target, String propertyName, int... values)
参数 描述
target 属性动画作用的对象,例如一个文本或者一个按钮
propertyName 动画所作用的属性
values 动画的过渡值,一般会在这里设置初始值和结束值,值类型为int
public static ObjectAnimator ofFloat(Object target, String propertyName, float... values)

ofFloat方法的使用和ofInt方法类似,唯一的区别为values的类型不同,ofFloat方法采用的是float类型。

public static ObjectAnimator ofObject(Object target, String propertyName,
        TypeEvaluator evaluator, Object... values)
参数 描述
target 属性动画作用的对象,例如一个文本或者一个按钮
propertyName 动画所作用的属性
evaluator 自定义的估值器
values 动画的过渡值,一般会在这里设置初始值和结束值

ofObject方法我们同样留待后面介绍估值器的时候再做介绍。下面我们以改变一个按钮的透明度为例,看下它的使用:

ObjectAnimator anim = ObjectAnimator.ofFloat(mButton, "alpha", 1.0f, 0.0f, 1.0f);
anim.setDuration(3000);
anim.start();

运行代码,效果如下所示:
在这里插入图片描述

而其它诸如修改缩放比例的代码则可以如下所示:

ObjectAnimator anim = ObjectAnimator.ofFloat(mButton, "scaleX", 1.0f, 1.5f, 1.0f);
anim.setDuration(1000);
anim.start();

总体而言使用起来非常简单,接下来我们看到下一个:AnimatorSet


四、AnimatorSet

AnimatorSet即动画集合,它有两种使用方式:XML形式和Java代码的形式,首先看到XML形式的使用。

1. XML形式

在属性动画的XML形式中,有下面几个标签可供选择:

标签 对应的类
<set> AnimatorSet
<animator> ValueAnimator
<objectAnimator> ObjectAnimator

下面是各个标签所对应的属性名称及其描述。

1.1 set标签

属性 描述
fillAfter 动画播放结束后是否固定,默认为true
interpolator 插值器设置,默认为加减速插值器
repeatMode 重复模式设置,课选择值有restart和reverse两种
repeatCount 重复次数,默认为0
startOffset 动画开启后的延时时间
startTime 设置开始动画的时刻

1.2 animator标签

属性 描述
duration 动画的持续时长,取值为int型数值,单位为毫秒
interpolator 动画的插值器设置,默认为加速减速插值器
repeatCount 重复次数,默认为0,取值为int型整数,代表重复次数
repeatMode 重复模式,有restart和reverse两种取值,reverse表示动画正反轮流执行,restart表示一直从头开始执行
startOffset 动画开始的延迟时间,取值为int型数值,单位为毫秒
valueFrom 动画的初始值,取值可以为int型、float型或颜色值,取值类型受valueType属性影响
valueTo 动画的结束值,取值可以为int型、float型或颜色值,取值类型受valueType属性影响
valueType value的取值类型,可以取intType或者floatType,如果值类型为颜色值,那么无需定义此属性

1.3 objectAnimator标签

objectAnimator标签的设置与animator的设置十分相似,animator标签可用的属性objectAnimator标签均可以用,下面只列举出部分objectAnimator特有的属性:

属性 描述
propertyName 表示属性动画作用对象的属性的名称

接下来通过一个例子来展示XML形式的使用:

// res/animator/anim_demo.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">

    <objectAnimator
        android:propertyName="alpha"
        android:valueType="floatType"
        android:valueFrom="1.0"
        android:valueTo="0.5"/>

    <objectAnimator
        android:propertyName="scaleX"
        android:valueType="floatType"
        android:valueFrom="1.0f"
        android:valueTo="1.5f"/>

</set>

在Java代码中,使用如下代码:

AnimatorSet animationSet =  (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.anim_demo);
animationSet.setTarget(mButton);
animationSet.start();

通过这种形式,我们就实现了在1s内同时改变按钮的透明度和x轴的伸缩的动画,效果如下所示:
在这里插入图片描述
以上就是关于AnimatorSet在XML形式下的使用,下面介绍Java代码形式的使用,这是一种更加推荐的用法。

2. Java代码形式

在Java代码中,我们只需要用到AnimatorSet类即可,下面我们先来介绍下这个类的常用 API:

方法 描述
setTarget 设置动画的作用对象,例如一个按钮
start 开启动画的方法
cancel 取消动画的方法
pause 暂停动画的方法
play 这个方法会返回一个Builder对象,传入的值为ValueAnimator对象或者ObjectAnimator对象,Builder类用于协助构造动画集合
with 将现有动画和传入的动画同时执行
before 将现有动画插入到传入的动画之前执行
after(Animator anim) 将现有动画插入到传入的动画之后执行
after(long delayTime) 将现有动画延迟指定毫秒后执行

接下来我们就通过一个实际的例子来展示它的使用。

ObjectAnimator alpha = ObjectAnimator.ofFloat(mButton, "alpha", 1.0f, 0.0f, 1.0f);
ObjectAnimator scaleX = ObjectAnimator.ofFloat(mButton, "scaleX", 1.0f, 1.5f, 1.0f);
ObjectAnimator rotate = ObjectAnimator.ofFloat(mButton, "rotationX", 0.0f, 360.0f);
AnimatorSet animationSet =  new AnimatorSet();
// 在进行x轴缩放之前,先同时进行透明度和旋转动画。
animationSet.play(rotate).with(alpha).before(scaleX);
animationSet.setDuration(5000);
animationSet.start();

运行代码,效果如下所示:
在这里插入图片描述
可以发现按钮先进行旋转和透明度动画(这两个是同时进行的),然后再进行x轴的拉伸动画。结果与我们的预期是相符的。


五、ViewPropertyAnimator

为了让我们能够更加轻松地使用属性动画,Android官方还为我们提供了一个面向对象的属性动画操作方式。它的使用方式如下所示:

View.animate().xxx().xxx();

我们这里以一个按钮动画为例展示它的使用:

mButton.animate().scaleX(2.0f).alpha(0.0f).setDuration(2000).setInterpolator(new LinearInterpolator());

效果如下所示:

在这里插入图片描述

需要注意的是这种设置下的动画是同时进行的,并且动画会自动启动,无需调用start方法。可以看到关于ViewPropertyAnimator的使用还是非常简单的,但我们只需要简单地对View中的一些常规属性进行动画操作时就可以考虑使用ViewPropertyAnimator。


六、属性动画的监听

属性动画提供了监听器用于监听动画的播放过程,主要有以下三个接口:AnimatorUpdateListenerAnimatorListenerAnimatorPauseListener

1. AnimatorUpdateListener

AnimatorUpdateListener接口的定义如下:

public static interface AnimatorUpdateListener {
    /**
     * <p>Notifies the occurrence of another frame of the animation.</p>
     *
     * @param animation The animation which was repeated.
     */
    void onAnimationUpdate(ValueAnimator animation);

}

可以看到这个接口中只有一个方法onAnimationUpdate,它会在动画属性值被更新的时候回调,也就是说在动画每播放一帧的时候它就会被回调一次。该监听通过addUpdateListener方法添加该监听事件。

2. AnimatorListener

AnimatorListener接口的定义如下:

public static interface AnimatorListener {
    void onAnimationStart(Animator animation);
    void onAnimationEnd(Animator animation);
    void onAnimationCancel(Animator animation);
    void onAnimationRepeat(Animator animation);
}

AnimatorListener接口则定义了四个方法,这四个方法会分别在动画开始、结束、取消、重播时被回调,我们可以通过addListener方法来添加该监听事件。

3. AnimatorPauseListener

相比上面两个接口,AnimatorPauseListener 的使用频率偏低,该接口定义了以下两个方法:

public static interface AnimatorPauseListener {
    /**
     * <p>Notifies that the animation was paused.</p>
     *
     * @param animation The animaton being paused.
     * @see #pause()
     */
    void onAnimationPause(Animator animation);

    /**
     * <p>Notifies that the animation was resumed, after being
     * previously paused.</p>
     *
     * @param animation The animation being resumed.
     * @see #resume()
     */
    void onAnimationResume(Animator animation);
}

这两个方法分别在动画暂停和暂停恢复时进行回调,可以通过addPauseListener方法添加该监听事件。


参考

《Android开发艺术探索》

  • 第7章 Android动画深入分析
    • 7.3 属性动画

Android属性动画完全解析(上),初识属性动画的基本用法


希望这篇文章对你有所帮助~

猜你喜欢

转载自blog.csdn.net/qq_38182125/article/details/89598061