Android动画基础 -- 属性动画

Android动画主要分为三类,帧动画、补间动画和属性动画

本篇博客一起来看属性动画

 

一、什么是属性动画

属性动画(Property Animation)是在Android3.0才推出的,并不像帧动画与补间动画一样很早就进入了江湖。那么后推出肯定是为了解决之前存在的某些问题,那么帧动画和补间动画存在什么问题呢?

帧动画和补间动画的局限性:

1)动画效果单一,可拓展性差

补间动画只能实现平移、旋转、缩放、透明度等一种或者多种动画的组合,如果遇到更复杂的动画需求,就会有点无力。

2)没有改变View的属性,只是改变视觉效果

再补间动画提到过,只是单纯的改变了View的视觉效果,而没有改变View的属性(上篇博客提到的点击事件的栗子)

3)作用目标单一

只能作用于View,而无法作用于View的属性

 

针对于这些需要优化的问题,便有了属性动画。可以作用于任意对象的任意属性,在一定时间间隔内,通过不断对值进行改变,并不断将该值赋给对象的属性,从而实现该对象在该属性上的动画效果

 

二、属性动画的使用

关于属性动画的使用,主要是两个动画类:ValueAnimator和ObjectAnimator,两个辅助类:插值器(决定值的变化模式(匀加速、匀速等)) & 估值器(决定具体的变化数值)

 

1)ValueAnimator

通过不断控制值的变化,再不断手动的赋给对象的属性,从而实现动画效果。

--> 设置动画的运行时长、动画效果对应属性的初始值结束值等 

--> 设置属性值从初始值过渡到结束值的变化逻辑 (ValueAnimator.ofInt()、ValueAnimator.ofFloat()、ValueAnimator.ofObject())

--> 根据上面的变化不断改变值

--> 值没改变一次,就手动赋值给对象的属性值一次

--> 每次赋值都调用invalidate()不断刷新视图

--> 不断循环上面两个步骤,直到结束

使用ValueAnimator,建议在Java代码中去写,更加灵活,举个栗子,这里用属性动画去改变Button的大小

// 步骤1:设置属性数值的初始值 & 结束值
        ValueAnimator valueAnimator = ValueAnimator.ofInt(mButton.getLayoutParams().width, 400);
        // 初始值 = 当前按钮的宽度,此处在xml文件中设置为200
        // 结束值 = 400
        // ValueAnimator.ofInt()内置了整型估值器,直接采用默认的.不需要设置
        // 即默认设置了如何从初始值200过渡到 结束值400

// 步骤2:设置动画的播放各种属性
        valueAnimator.setDuration(2000);
        // 设置动画运行时长:1s

// 步骤3:将属性数值手动赋值给对象的属性:此处是将 值 赋给 按钮的宽度
        // 设置更新监听器:即数值每次变化更新都会调用该方法
        valueAnimator.addUpdateListener(new AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animator) {

                int currentValue = (Integer) animator.getAnimatedValue();
                // 获得每次变化后的属性值
                System.out.println(currentValue);
                // 输出每次变化后的属性值进行查看

                mButton.getLayoutParams().width = currentValue;
                // 每次值变化时,将值手动赋值给对象的属性
                // 即将每次变化后的值 赋 给按钮的宽度,这样就实现了按钮宽度属性的动态变化

// 步骤4:刷新视图,即重新绘制,从而实现动画效果
                mButton.requestLayout();
                
            }
        });

        valueAnimator.start();
        // 启动动画

    }

ValueAnimator.ofFloat的使用方式与ValueAnimator.ofInt一样,只不过是以浮点数的形式,将开始值过度到结束值;同理,ValueAnimator.ofObject是将初始值以对象的形式过渡到了结束值,例如这个对象可以是圆(封装了原点坐标和半径)、矩形(封装了长宽坐标)等。

在使用ValueAnimator.ofObject之前,我们需要先理解上面提到的估值器(TypeEvaluator)

看到这里可能小伙伴会有疑问,为什么在使用ValueAnimator.ofFloat和ValueAnimator.ofInt的时候,没有提到估值器呢?因为在这两个方法中,系统已经设置了两个默认的估值器IntEvaluator和FloatEvaluator,通过查看源码即可知

public static ValueAnimator ofFloat(float... values) {
        ValueAnimator anim = new ValueAnimator();
        anim.setFloatValues(values);
        return anim;
    }

ofFloat方法里调用了setFloatValues方法

public void setFloatValues(float... values) {
        if (values == null || values.length == 0) {
            return;
        }
        if (mValues == null || mValues.length == 0) {
            setValues(PropertyValuesHolder.ofFloat("", values));
        } else {
            PropertyValuesHolder valuesHolder = mValues[0];
            valuesHolder.setFloatValues(values);
        }
        // New property/values/target should cause re-initialization prior to starting
        mInitialized = false;
    }

在setFloatValues方法里查看到PropertyValuesHolder 

// type evaluators for the primitive types handled by this implementation
    private static final TypeEvaluator sIntEvaluator = new IntEvaluator();
    private static final TypeEvaluator sFloatEvaluator = new FloatEvaluator();

这里便有IntEvaluator和FloatEvaluator的具体实现

但是对于ObjectEvaluator,操纵的是对象,具有高度封装及个性化的特性,所有需要开发者自己去实现估值器,可以模仿FloatEvaluator或者IntEvaluator的写法,毕竟源码是最好的学习资料

public class FloatEvaluator implements TypeEvaluator {  
// FloatEvaluator实现了TypeEvaluator接口

// 重写evaluate()
    public Object evaluate(float fraction, Object startValue, Object endValue) {  
// 参数说明
// fraction:表示动画完成度(根据它来计算当前动画的值)
// startValue、endValue:动画的初始值和结束值
        float startFloat = ((Number) startValue).floatValue();  
        
        return startFloat + fraction * (((Number) endValue).floatValue() - startFloat);  
        // 初始值 过渡 到结束值 的算法是:
        // 1. 用结束值减去初始值,算出它们之间的差值
        // 2. 用上述差值乘以fraction系数
        // 3. 再加上初始值,就得到当前动画的值
    }  
}  

看了FloatEvaluater的实现,我们自定义一个类也去实现TypeEvaluator

// 实现TypeEvaluator接口
public class ObjectEvaluator implements TypeEvaluator{  

// 复写evaluate()
// 在evaluate()里写入对象动画过渡的逻辑
    @Override  
    public Object evaluate(float fraction, Object startValue, Object endValue) {  
        // 参数说明
        // fraction:表示动画完成度(根据它来计算当前动画的值)
        // startValue、endValue:动画的初始值和结束值

        ... // 写入对象动画过渡的逻辑
        
        return value;  
        // 返回对象动画过渡的逻辑计算后的值
    }  
  

 

2)ObjectAnimator

通过不断控制值的变化,再不断自动的赋给对象的属性,从而实现动画效果。

--> 设置动画的运行时长、动画效果对应属性的初始值结束值等 

--> 设置属性值从初始值过渡到结束值的变化逻辑 

--> 根据上面的变化不断改变值

--> 值没改变一次,就自动赋值给对象的属性值一次

--> 每次赋值都调用invalidate()不断刷新视图

--> 不断循环上面两个步骤,直到结束

看完ObjectAnimator的定义,发现与ValueAnimator本质上一样,不同点则是ValueAnimator需要手动赋值,而ObjectAnimator是自动赋值。

 

三、总结

估值器与插值器

定义:

插值器:一个辅助动画实现的接口

插值器:一个辅助动画插值器的接口(属性动画特有)

作用:

估值器:设置属性值从初始值过度到结束值的变化规律(如匀速、先匀加速后匀减速等)

插值器:设置属性值从初始值过度到结束值的具体变化数值(插值器决定值的变化规律和趋势,而接下来具体的数值变化则交给估值器)

 

ValueAnimator:先改变值,然后手动赋值给对象的属性,从而实现动画(间接对对象属性进行操作)

ObjectAnimator:继承自ValueAnimator,先改变值,然后自动赋值给对象属性从而实现动画(直接对对象进行操作)

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值