欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android动画系列之属性动画(Property Animation)详解

程序员文章站 2022-03-16 16:47:22
...

Android动画系列之属性动画(Property Animation)详解

1、简介

Property Animation官方链接

属性动画可以让任何对象加上动画效果。可以定义一个动画来改变任何对象属性,无论它是否显示在屏幕上。在指定的时间长度,属性动画改变属性值。通过指定对象属性来创造动画效果,比如View在屏幕上的位置,动画的时长,以及动画值的改变。

属性动画系统可以让定义一个动画的以下特征:

  • 持续时间(Duration):可以指定一个动画的持续时间。默认长度为300毫秒。
  • 时间插值器(Time interpolation):可以指定属性的值如何计算作为动画当前所用时间的函数。
  • 重复和行为(Repeat count and behavior):可以指定是否有一个动画重复时,达到持续时间的结束,有多少次重复动画。您还可以指定是否希望动画反向播放。设置它反向播放动画,然后反复重复,直到达到重复的数量。
  • 动画设置(Animator Sets):可以让动画成逻辑组,同时或顺序或在指定的延迟。
  • 帧刷新延迟(Frame refresh delay):可以指定如何经常刷新动画帧。默认设置为刷新每10毫秒,但应用程序可以刷新帧的速度最终取决于系统的整体是如何的,以及该系统可以为底层定时器服务的速度。 一般使用系统默认即可。

2、属性动画与补间动画的区别

补间动画只能作用于View对象,所以如果您想要作用于非View对象时,必须实现自己的代码。视图动画系统也受到限制,因为它只公开了View对象来动画,例如视图的缩放和旋转,而不是背景色。

补间动画的另一个缺点是它只修改了视图绘制的位置,而不是实际视图本身。例如,如果您动画一个按钮以在屏幕上移动,则该按钮的绘制正确,但是您可以单击该按钮的实际位置不会改变,因此您必须实现自己的逻辑来处理这个问题。

使用属性动画,这些约束将被完全解除,您可以对任何对象(视图和非视图)的任何属性进行动画化,并且对象本身实际上是被修改的。从更高层次上来说,您可以为要动画的属性(如颜色、位置或大小)添加动画,并可以定义动画的各个方面,如通过插值器或者多个动画的同步。

然而,补间动画需要更少的时间来设置,并且需要更少的代码来编写。如果补间动画完成了您需要做的所有事情,或者您的现有代码已经按照您想要的方式工作,则不需要使用属性动画系统。所以,根据不同场合来选择合适的动画,是最好的选择。

3、API概述

3.1、ValueAnimator

ValueAnimator API文档

这是整个属性动画的核心类,它封装了为动画设置起始值、结束值、持续时间以及如何重复等方法 ,当然还有监听变化值的回调方法。但是,ValueAnimator并没有将实时监听的变化值设置到目标对象的指定属性上,所以您必须手动设置。

3.1.1、ValueAnimator主要方法:
  • addUpdateListener(ValueAnimator.AnimatorUpdateListener listener):
  • getAnimatedValue():获取只有一个属性时的动画当前进行值
  • getAnimatedValue(String propertyName):根据属性名称获取当前的动画进行值
  • ofArgb(int… values):构造并返回在颜色值之间ValueAnimator对象
  • ofFloat(float… values):构造并返回在浮点值之间ValueAnimator对象
  • ofInt(int… values):构造并返回在整型之间ValueAnimator对象
  • ofObject(TypeEvaluator evaluator, Object… values):构造并返回在对象之间ValueAnimator对象
  • ofPropertyValuesHolder(PropertyValuesHolder… values):构造并返回在PropertyValuesHolder对象中指定的值之间的ValueAnimator对象,用于实现实现组合动画
3.1.2、ValueAnimator的使用

1、通过几个of方法获取ValueAnimator的实例,并设置属性的变化值开始与结束值;

2、设置动画的播放各种属性,如动画时长,是否循环等;

3、为动画设置监听addUpdateListener,在监听里面获取属性的变化值,将改变后的值赋给对象的属性值,然后刷新视图;

4、启动动画。

下面将通过改变button的宽度这个例子来演示:

/**
     * 将btn1的宽度由200px延展到800px
     */
    private void ofInt1(){
        //1、设置属性数值的初始值 & 结束值
        ValueAnimator valueAnimator = ValueAnimator.ofInt(200,800);

        //2:设置动画的播放各种属性
        valueAnimator.setDuration(3000);

        //3、添加监听
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                //获得每次变化后的属性值
                int currentValue = (int) animation.getAnimatedValue();

                //手动将变化的值赋给对象的属性
                btn1.getLayoutParams().width = currentValue;

                //刷新视图
                btn1.requestLayout();
            }
        });

        //4、启动动画
        valueAnimator.start();
    }

ValueAnimator.ofObject()的本质还是操作 * 值 *,只是是采用将 多个值 封装到一个对象里的方式 同时对多个值一起操作而已

3.2、ObjectAnimator

ObjectAnimator API文档链接

ObjectAnimator是ValueAnimator的子类,可以直接对对象的属性赋值进行操作。一般情况下都是使用ObjectAnimator。

想要正确的使用objectanimator更新属性,必须做到以下几点:

  • objectanimator 更新 动画的对象属性必须有一个setter函数的形式设置属性名。因为objectanimator依赖setter函数来自动更新动画,它必须能够与这个setter方法访问属性
    。例如想要修改一个属性width,必须存在setWidth方法。如果setter方法不存在,有三个选项:
    • 如果有权限则将setter方法添加到类中。
    • 使用您有权更改的包装类,并让该包装器使用有效的setter方法接收值,并将其转发给原始对象。
    • 使用ValueAnimator
  • 如果您在调用of方法创建动画时只传入了一个属性值(而不是既有启始值和终止值),那么系统将默认把这个值视为终止值,这就需要该属性包含getter()方法,以获得其初始值,getter()方法的命名规则与setter()方法一致
  • getter()方法获取值的类型与setter()方法设置值的类型必须相同
  • 实现动画的效果可能需要调用invalidate()方法强制view重绘,这需要在onAnimationUpdate()的回调方法中进行

ObjectAnimator的使用方法是类似ValueAnimator:

//第一个参数是需要设置动画的对象,第二个参数是需要改变的属性名称
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(iv1,"alpha",0f,1f);
        objectAnimator.setDuration(3000);
        objectAnimator.start();

常用的ObjectAnimator属性:

属性 作用 数值类型
alpha 控制透明度 float
rotation 控制旋转角度 float
translationX x方向的位移 float
translationX y方向的位移 float
scaleX X方向的缩放倍数 float
scaleY Y方向的缩放倍数 float
rotationX 以X轴为轴的旋转度数 float
rotationY 以Y轴为轴的旋转度数 float
3.3、AnimatorSet

AnimatorSet API文档链接

AnimatorSet播放一组Animator对象按指定的顺序排列。动画可以设置为一起播放,顺序,或在指定的延迟之后。、

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

  • after(long delay):将现有动画延迟指定毫秒后执行
  • after(Animator anim):将现有动画插入到传入的动画之后执行
  • before(Animator anim):将现有动画插入到传入的动画之前执行
  • with(Animator anim):将现有动画和传入的动画同时执行
4、xml使用属性动画

在xml中一共可以使用三种标签:

  • ValueAnimator - animator
  • ObjectAnimator - objectAnimator
  • AnimatorSet - set

使用的时候在res/animator下新建xml文件

<set xmlns:android="http://schemas.android.com/apk/res/android"
     android:ordering="sequentially">

    <animator
        android:duration="3000"
        android:startOffset="1000"
        android:valueFrom="200px"
        android:valueTo="800px"
        android:valueType="intType"/>

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

其中android:ordering=”sequentially”这个属性共有两个值:

  • sequentially:按顺序播放
  • together:同时播放

在代码中载入动画:


Animator animator = AnimatorInflater.loadAnimator(context, R.animator.anim_file);
animator.setTarget(view);
animator.start();
5、ViewGroup容器布局动画

属性动画系统提供了对ViewGroup对象进行动画化更改的功能,并提供了一种简单的方法来对视图对象本身进行动画化。
控件可以在ViewGroup中通过设置LayoutTransition对布局更改进行动画化。
LayoutTransition的动画效果都是设置给ViewGroup,然后当被设置动画的ViewGroup中添加删除View时体现出来。该类用于当前布局容器中有View添加、删除、隐藏、显示等时候定义布局容器自身的动画和View的动画.

LayoutTransition有下面几种转换类型动画:

  • APPEARING:当View出现或者添加的时候View出现的动画
  • CHANGE_APPEARING:当添加View导致布局容器改变的时候整个布局容器的动画。
  • DISAPPEARING:当View消失或者隐藏的时候View消失的动画
  • CHANGE_DISAPPEARING:当删除或者隐藏View导致布局容器改变的时候整个布局容器的动画
  • CHANGING:不是由于View出现或消失造成对其他View位置造成改变的时候整个布局容器的动画

使用的时候只要将ViewGroup的android:animateLayoutchanges属性设置为true,即可使用默认的动画:

<LinearLayout
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:id="@+id/verticalContainer"
    android:animateLayoutChanges="true" />

如果要使用自己的自定义动画,可以通过调用LayoutTransition的setAnimator()设置自定义的动画。

具体可参考Android属性动画Property Animation系列三之LayoutTransition(布局容器动画)

6、PropertyValuesHolder与Keyframe

PropertyValuesHolder可以生成操作几个属性的动画,可实现组合动画。

Keyframe关键帧,可以设置对应时间的的值,配合PropertyValuesHolder使用。

详细介绍可参考PropertyValuesHolder与Keyframe

7、StateListAnimator

通过StateListAnimator各种动画的搭配,我们能为不同状态下的控件提供各种动画效果。

StateListAnimator在API21才引入的,所以在5.0以上的系统才有效果。

在res/animator中新建selector文件:

<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_pressed="true">
        <set>
            <objectAnimator android:propertyName="scaleX"
                            android:duration="@android:integer/config_shortAnimTime"
                            android:valueTo="1.5"
                            android:valueType="floatType"/>
            <objectAnimator android:propertyName="scaleY"
                            android:duration="@android:integer/config_shortAnimTime"
                            android:valueTo="1.5"
                            android:valueType="floatType"/>
        </set>
    </item>
    <item android:state_pressed="false">
        <set>
            <objectAnimator android:propertyName="scaleX"
                            android:duration="@android:integer/config_shortAnimTime"
                            android:valueTo="1"
                            android:valueType="floatType"/>
            <objectAnimator android:propertyName="scaleY"
                            android:duration="@android:integer/config_shortAnimTime"
                            android:valueTo="1"
                            android:valueType="floatType"/>
        </set>
    </item>

</selector>

可以在xml文件中设置:

android:stateListAnimator=”@animator/selector_animate_scale”

也可以通过代码设置:

StateListAnimator animator = AnimatorInflater.loadStateListAnimator(this, R.animator.selector_animate_scale);
 btnStateListAnim.setStateListAnimator(animator);
8、ViewPropertyAnimator

ViewPropertyAnimator提供一种简单的方法来动画View并行地使用单个基础Animator对象。它的行为很像一个ObjectAnimator,因为它修改视图属性的实际值,但在同时动画多个属性时效率更高。

它的用法如下:

btnViewProperty.animate().x(500).y(500).start();

ViewPropertyAnimator还有好多便捷的方法:

alpha(float value),rotation(float value),scaleX(float value),translationX(float value)等等。
详情见ViewPropertyAnimator API文档

9、插值器和估值器的使用

参考Android动画系列之插值器(Interpolator)和估值器(TypeEvaluator)详解

Github示例代码