Android--浅析ObjectAnimator类

本周做一个动画的时候用到了ObjectAnimator,动画要求,一个柱状图根据数值的不同慢慢升起,但是使用了ObjectAnimator类的时候,发现该类并不能满足我的需求,后来使用了它的父类ValueAnimator,十分简单的解决了这个问题。

首先介绍下ObjectAnimator:

 

public final class ObjectAnimator extends ValueAnimator

ObjectAnimator内部实现的比较常用的方法有:

 

 

我们可以采用以下这种形式进行运用(比如旋转动画):

ObjectAnimatoranimator = ObjectAnimator.ofFloat(tv,"rotation",0,180,0);

animator.setDuration(2000);

animator.start();

 

 

首先看ObjectAnimator.ofFloat()和ObjectAnimator.ofInt()这两个方法:

 

public static ObjectAnimator ofFloat(Object target, String propertyName, float... values) {
    ObjectAnimator anim = new ObjectAnimator(target, propertyName);
    anim.setFloatValues(values);
    return anim;
}

 

public static ObjectAnimator ofInt(Object target, String propertyName, int... values) {
    ObjectAnimator anim = new ObjectAnimator(target, propertyName);
    anim.setIntValues(values);
    return anim;
}

 

 

简单的理解是两者方法的参数表第一个都是一个对象,也就是我们设置动画的view,第二个是代表动画的String ,比如”alpha”, “rotation”等等,第三个是一个参数序列,内部都实现了一个ObjectAnimator的实例,但是ofFloat设置的是浮点型数据, ofInt设置的时候整型数据,两者都返回了一个ObjectAnimator的实例。

 

那么构造方法实现的是什么呢?

 

private ObjectAnimator(Object target, String propertyName) {
    setTarget(target);
    setPropertyName(propertyName);
}

 

setTarget()方法:顾名思义就是设置当前属性动画的对象,对于对象产生了一个弱引用,便于修改对象的属性。

 

@Override
public void setTarget(@Nullable Object target) {
    final Object oldTarget = getTarget();
    if (oldTarget != target) {
        if (isStarted()) {
            cancel();
        }
        mTarget = target == null ? null : new WeakReference<Object>(target);
        // New target should cause re-initialization prior to starting
        mInitialized = false;
    }
}

 

setPropertyName()方法,利用字符串对象propertyName设置对应的动画

 

 

 

View中也没有rotation这个属性。那它是怎么来改变这个值的呢?其实,ObjectAnimator做动画,并不是根据控件xml中的属性来改变的,而是通过指定属性所对应的set方法来改变的。比如,我们指定的改变rotation的属性值,ObjectAnimator在做动画时就会到指定控件(TextView)中去找对应的setRotation()方法来改变控件中对应的值。同样的道理,当我们在最开始的示例代码中,指定改变”alpha”属性值的时候,ObjectAnimator也会到TextView中去找对应的setAlpha()方法。那TextView中都有这些方法吗,有的,这些方法都是从View中继承过来的,在View中有关动画,总共有下面几组set方法:

//1、透明度:alpha

publicvoidsetAlpha(floatalpha)

 

//2、旋转度数:rotation、rotationX、rotationY

publicvoidsetRotation(floatrotation)

publicvoidsetRotationX(floatrotationX)

publicvoidsetRotationY(floatrotationY)

 

//3、平移:translationX、translationY

publicvoidsetTranslationX(floattranslationX)

publicvoidsetTranslationY(floattranslationY)

 

//缩放:scaleX、scaleY

publicvoidsetScaleX(floatscaleX)

publicvoidsetScaleY(floatscaleY)

可以看到在View中已经实现了有关alpha,rotaion,translate,scale相关的set方法。所以我们在构造ObjectAnimator时可以直接使用。
在开始逐个看这些函数的使用方法前,我们先做一个总结:
1
、要使用ObjectAnimator来构造对画,要操作的控件中,必须存在对应的属性的set方法
2
setter 方法的命名必须以骆驼拼写法命名,即set后每个单词首字母大写,其余字母小写,即类似于setPropertyName所对应的属性为propertyName

 

 

ObjectAnimator的动画的实现原理

 

 

ValueAnimator的动画流程与ObjectAnimator的动画流程做了个对比。
可以看到ObjectAnimator的动画流程中,也是首先通过加速器产生当前进度的百分比,然后再经过Evaluator生成对应百分比所对应的数字值。这两步与ValueAnimator是完全一样的,唯一不同的是最后一步,在ValueAnimator中,我们要通过添加监听器来监听当前数字值。而在ObjectAnimator中,则是先根据属性值拼装成对应的set函数的名字,比如这里的scaleY的拼装方法就是将属性的第一个字母强制大写后,与set拼接,所以就是setScaleY。然后通过反射找到对应控件的setScaleY(float scaleY)函数,将当前数字值做为setScaleY(floatscale)的参数将其传入。
这里在找到控件的set函数以后,是通过反射来调用这个函数的,有关反射的使用大家可以参考《夯实JAVA基本之二——反射(1):基本类周边信息获取》 
这就是ObjectAnimator的流程,最后一步总结起来就是调用对应属性的set方法,将动画当前数字值做为参数传进去。

 

下面是几个常用的函数

**

 * 设置动画时长,单位是毫秒

 */

ValueAnimator setDuration(long duration)

/**

 * 获取ValueAnimator在运动时,当前运动点的值

 */

Object getAnimatedValue();

/**

 * 开始动画

 */

void start()

/**

 * 设置循环次数,设置为INFINITE表示无限循环

 */

void setRepeatCount(int value)

/**

 * 设置循环模式

 * value取值有RESTART,REVERSE,

 */

void setRepeatMode(int value)

/**

 * 取消动画

 */

void cancel()

(2)、监听器相关

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

/**

 * 监听器一:监听动画变化时的实时值

 */

public static interface AnimatorUpdateListener {

    void onAnimationUpdate(ValueAnimator animation);

}

//添加方法为:public void addUpdateListener(AnimatorUpdateListener listener)

/**

 * 监听器二:监听动画变化时四个状态

 */

public static interface AnimatorListener {

    void onAnimationStart(Animator animation);

    void onAnimationEnd(Animator animation);

    void onAnimationCancel(Animator animation);

    void onAnimationRepeat(Animator animation);

}

//添加方法为:public void addListener(AnimatorListener listener)

(3)、插值器与Evaluator

?

1

2

3

4

5

6

7

8

/**

 * 设置插值器

 */

public void setInterpolator(TimeInterpolator value)

/**

 * 设置Evaluator

 */

public void setEvaluator(TypeEvaluator value)

 

 

而ValusAnimator的用法,如下图

    private void performAnimate(final Viewtarget, final int start, final int end) {

        ValueAnimator valueAnimator =ValueAnimator.ofInt(1, 100);

        valueAnimator.addUpdateListener(newValueAnimator.AnimatorUpdateListener() {

 

            //持有一个IntEvaluator对象,方便下面估值的时候使用

            private IntEvaluator mEvaluator =new IntEvaluator();

            @Override

            public voidonAnimationUpdate(ValueAnimator animator) {

                //获得当前动画的进度值,整型,1-100之间

                int currentValue = (Integer)animator.getAnimatedValue();

                //计算当前进度占整个动画过程的比例,浮点型,0-1之间

                float fraction = currentValue /100f;

                //这里我偷懒了,不过有现成的干吗不用呢

                //直接调用整型估值器通过比例计算出宽度,然后再设给Button

                target.getLayoutParams().height= mEvaluator.evaluate(fraction, start, end);

                target.requestLayout();

            }

        });

       valueAnimator.setDuration(5000).start();

}

 

也就是说ValueAnimator实际上并不对对象进行修改,只是计算了一系列的数值,我们需要自己对ValueAnimator设置监听器进行回调,并在其中设置对象的属性,达到动画的效果。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值