Android动画深入分析-属性动画初级用法

一、 属性动画引入的背景

1、view动画的不足之处

1、作用的对象只能是view
2、只能播放view的四种动画或动画组合(透明渐变、平移、缩放、旋转)
3、非view对象不能使用view动画
4、太局限 灵活性差
5、补间动画还有一个致命的缺陷,就是它只是改变了View的显示效果而已,而不会真正去改变View的属性。(这点可以给按钮设置点击事件进行平移动画测试点击位置)

2、属性动画

属性动画机制已经不再是针对于View来设计的了。它实际上是一种不断地对值进行操作的机制,并将值赋值到指定对象的指定属性上,可以是任意对象的任意属性。我们只需要告诉系统动画的运行时长,需要执行哪种类型的动画,以及动画的初始值和结束值,剩下的工作就可以全部交给系统去完成了。

3、几个常用的类
  • Animator 属性动画基类
  • ValueAnimator 值动画
  • ObjectAnimator 对象动画
  • AnimatorSet 属性动画集合
4、几个类之间关系

(1)动画基类Animator :
在这里插入图片描述

属性动画基类

(2)关系类图

在这里插入图片描述

二、属性动画

1、ValueAnimator

(1)ValueAnimator简介

由于Animator是抽象类,ValueAnimator 是直接继承 Animator的。ValueAnimator还负责管理动画的播放次数、播放模式、以及对动画设置监听器等(Animator的这些方法都在ValueAnimator 实现),确实是一个非常重要的类。所以ValueAnimator 是整个属性动画机制当中最核心的一个类。

(2)属性动画工作机制

属性动画的运行机制是通过不断地对值进行操作来实现的,而初始值和结束值之间的动画过渡就是由ValueAnimator这个类来负责计算的。它的内部使用一种时间循环的机制来计算值与值之间的动画过渡,我们只需要将初始值和结束值提供给ValueAnimator,并且告诉它动画所需运行的时长,那么ValueAnimator就会自动帮我们完成从初始值平滑地过渡到结束值这样的效果。

(3)ValueAnimator 的使用

通过上文我们了解 属性动画可以作用于任何对象,其实也可以不作用对象而直接播放动画(如下栗子)

ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f, 1f);
        valueAnimator.setDuration(400);
        valueAnimator.start();
// 这样就开启了一个简单的动画,表示吧一个值从0变化到1,执行时长300ms。

不作用与对象也可以播放动画?哇真的很强大,可是不作用对象我们运行代码怎没看到?怎没确定动画播放了?我们可以设置动画监听啊!!!栗子如下:

ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f, 1f);
        valueAnimator.setDuration(400);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float value = (float) animation.getAnimatedValue();
                Log.i("blabla", "onAnimationUpdate: " + value);
            }
        });
        valueAnimator.start();
        
        // log 如下,可以看到数值从0到1平滑的改变。
        
2019-06-11 10:38:15.289 25924-25924/com.example.myapplication I/blabla: onAnimationUpdate: 0.0
2019-06-11 10:38:15.331 25924-25924/com.example.myapplication I/blabla: onAnimationUpdate: 0.0
2019-06-11 10:38:15.505 25924-25924/com.example.myapplication I/blabla: onAnimationUpdate: 0.36806342
2019-06-11 10:38:15.608 25924-25924/com.example.myapplication I/blabla: onAnimationUpdate: 0.7477293
2019-06-11 10:38:15.642 25924-25924/com.example.myapplication I/blabla: onAnimationUpdate: 0.8535534
2019-06-11 10:38:15.650 25924-25924/com.example.myapplication I/blabla: onAnimationUpdate: 0.89507747
2019-06-11 10:38:15.703 25924-25924/com.example.myapplication I/blabla: onAnimationUpdate: 0.9822787
2019-06-11 10:38:15.716 25924-25924/com.example.myapplication I/blabla: onAnimationUpdate: 0.99554986
2019-06-11 10:38:15.730 25924-25924/com.example.myapplication I/blabla: onAnimationUpdate: 1.0

ofFloat方法:

  * @param values A set of values that the animation will animate between over time.
     * @return A ValueAnimator object that is set up to animate between the given values.
     */
    public static ValueAnimator ofFloat(float... values) {
        ValueAnimator anim = new ValueAnimator();
        anim.setFloatValues(values);
        return anim;
    }

这个方法表示改变的值为float类型。参数为可变参数,代表值在这些参数内变化。如上我们设置0-1代表300ms内从0变化到1。假如我们设置0,1,3。数值将0变化到1再变化到3。

ofInt方法:

和ofFloat类似,只是数值为int类型而不是小数类型。也是比较常用的方法

ofObject方法:

ObjectAnimator 中用的多,在ObjectAnimator 使用中再总结。

其他方法:

  • setStartDelay 设置动画延迟播放时间
  • setRepeatCount 设置动画循环次数
  • setRepeatMode 设置动画循环播放模式(RESTART:重新播放,REVERSE:倒序播放)
2、ObjectAnimator

(1)ValueAnimator 的特点

1、对值操作
2、值平滑的发生变化
3、平时使用场景不多

(2)ObjectAnimator特点

1、对对象的属性进行操作
2、相比于ValueAnimator,ObjectAnimator可能才是我们最常接触到的类
3、它其实是继承自ValueAnimator的,底层的动画实现机制也是基于ValueAnimator来完成的

方法ofFloat

     * @param target The object whose property is to be animated. This object should
     * @param propertyName The name of the property being animated.
     * @param values A set of values that the animation will animate between over time.
     * @return An ObjectAnimator object that is set up to animate between the given values.
     */
    public static ObjectAnimator ofFloat(Object target, String propertyName, float... values) {
        ObjectAnimator anim = new ObjectAnimator(target, propertyName);
        anim.setFloatValues(values);
        return anim;
    }
    

和ValueAnimator 的ofFloat类似,有点小改动。
1、Object target 要操作的对象,对哪个对象进行动画。
2、String propertyName 要操作对象的属性,对哪个对象的属性进行动画。
3、 float… values 可变参数(值变化范围,这点和ValueAnimator 的ofFloat的参数一样)
简单例子如下:

       button = findViewById(R.id.btn);
//         参数1: object 对象
//         参数2: 操作的属性 (属性要有get set方法)
//          3-n  :  可变参数 要执行动画的数值变化范围
        ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(button, "rotation", 0f, 360f);
        objectAnimator.setDuration(5000);
        objectAnimator.start();

动画效果:按钮旋转360度
有了旋转rotation,其实我们也可以设置属性为:

  • alpha(透明度变化)
  • translationX(x轴方向平移)
  • translationY(y轴方向平移)
  • scaleY
  • scaleX
  • 等等

或许我们疑问:ObjectAnimator的ofFloat的第二个参数可以为那些属性值?上面我们知道可以传alpha、translationX、translationY、scaleY、scaleX等等。其实我们可以传入任意的值到ofFloat()方法的第二个参数当中。但事实就是如此。因为ObjectAnimator在设计的时候就没有针对于View来进行设计,而是针对于任意对象的,它所负责的工作就是不断地向某个对象中的某个属性进行赋值,然后对象根据属性值的改变再来决定如何展现出来。

(3)上述按钮动画栗子分析

1、其实这段代码的意思就是ObjectAnimator会帮我们不断地改变Button对象中rotation属性的值,从0f变化到360f。然后button对象需要根据rotation属性值的改变来不断刷新界面的显示,从而让用户可以看出旋转的动画效果。
2、那么button对象中是不是有rotation属性这个值呢?没有,不仅button没有这个属性,连它所有的父类也是没有这个属性的!这就奇怪了,button当中并没有rotation这个属性,ObjectAnimator是如何进行操作的呢?其实ObjectAnimator内部的工作机制并不是直接对我们传入的属性名进行操作的,而是会去寻找这个属性名对应的get和set方法,因此rotation属性所对应的get和set方法应该就是(如下代码)
3、那么button对象中是否有这两个方法呢?确实有,并且这两个方法是由View对象提供的,也就是说不仅button可以使用这个属性来进行淡入淡出动画操作,任何继承自View的对象都可以的。
4、既然rotation 可以那么我们上述说的alpha等等都可以了
ps:对象要有get set方法才能进行属性动画

public void setRotation(float value);
public float getRotation();
3、AnimatorSet-属性动画集合

(1)控制动画播放顺序的api

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

这几个api的返回值都是AnimatorSet.Builder类型实例,builder模式链式调用(如下play的源码)

//AnimatorSet的方法
public Builder play(Animator anim) {
        if (anim != null) {
            return new Builder(anim);
        }
        return null;
    }

(2)栗子

        // 旋转
        ObjectAnimator rotation = ObjectAnimator.ofFloat(button, "rotation", 0f, 360f);
        // 平移
        float translationX = button.getTranslationX();
        ObjectAnimator translation = ObjectAnimator.ofFloat(button, "translationX", translationX, -500f, translationX);
        // 透明
        ObjectAnimator fadeInOut = ObjectAnimator.ofFloat(button, "alpha", 1f, 0f, 1f);
        // 动画集合播放上述动画
        AnimatorSet animatorSet = new AnimatorSet();
        // 先播放 translation 再同时播放rotation、fadeInOut
        animatorSet.play(rotation).with(fadeInOut).after(translation);
        animatorSet.setDuration(3000);
        animatorSet.start();

(4)Animator监听器

动画怎没能没有监听呢?所以Animator提供了监听方法addListener(AnimatorListener listener),我们只需要实现这个listener就行啦。。。。。由于这方法是Animator提供所以属性动画通用。

  • AnimatorListener
 AnimatorSet animatorSet = new AnimatorSet();
        animatorSet.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {
                Log.i("blabla", "onAnimationStart: ");
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                Log.i("blabla", "onAnimationEnd: ");
            }

            @Override
            public void onAnimationCancel(Animator animation) {
                Log.i("blabla", "onAnimationCancel: ");
            }

            @Override
            public void onAnimationRepeat(Animator animation) {
                Log.i("blabla", "onAnimationRepeat: ");
            }
        });
  • AnimatorListenerAdapter

如上AnimatorListener使用时需要重写四个方法但是有时候我们可能不需要重写这么多,有时我们可能只需要重写一个,这时Android提供了一个适配器类,叫作AnimatorListenerAdapter,使用这个类就可以解决掉实现接口繁琐的问题了。(栗子如下)

 AnimatorSet animatorSet = new AnimatorSet();
        animatorSet.addListener(new AnimatorListenerAdapter() {
            // 重写想使用的方法即可
            @Override
            public void onAnimationStart(Animator animation) {
                // todo
            }
        });

三、属性动画的xml实现

我们可以使用代码来编写所有的动画功能,这也是最常用的一种做法。不过,过去的补间动画除了使用代码编写之外也是可以使用XML编写的,因此属性动画也提供了这一功能,即通过XML来完成和代码一样的属性动画功能。

1、xml编写的优缺点

优点:
代码重用方便
缺点:
编写相对java代码麻烦
扩展性不高(比如动态获得手机信息就需要java代码实现)

2、标签
  • animator 对应代码中的ValueAnimator
  • objectAnimator 对应代码中的ObjectAnimator
  • set 对应代码中的AnimatorSet
3、编写步骤

首先要在res目录下面新建一个animator文件夹
在这里插入图片描述

4、栗子

(1)从0到100平滑过渡的动画

<animator android:duration="3000"
    android:valueFrom="0"
    android:valueTo="1"
    android:valueType="floatType"/>

(2)将一个视图的alpha属性从1变成0

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

(3)组合动画

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <animator
        android:duration="3000"
        android:valueFrom="0"
        android:valueTo="1"
        android:valueType="floatType" />
    <objectAnimator
        android:valueFrom="0"
        android:valueTo="1"
        android:valueType="floatType"
        android:propertyName="alpha"/>
</set>
5、 xml动画资源加载
 Animator animator = AnimatorInflater.loadAnimator(this, R.animator.test);
       animator.setTarget(button);
       animator.start();

end

参考:
1、安卓开发艺术探索
2、https://blog.csdn.net/guolin_blog/article/details/43536355

属性动画中级用法

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值