«

安卓 属性动画 ValueAnimator ObjectAnimator 源码分析 关键处

时间:2024-3-2 19:08     作者:韩俊     分类: Android


属性动画 是 3.0后面的,
—-实际上, 这是因为 谷歌 把这个 nineold开源框架 给纳入到 sdk 而己.
—-但为了 支持 3.0之前的版本, 我们估计还是得 使用这个开源框架的.

这里对 属性动画 源码的分析, 并不打算做得很具体. 这里仅仅是进行一些简要的介绍, 特别是介绍看懂源码所必须看懂的类. 如果搞明白了这几个类, 相信属性动画的源码 读者 是可以很容易看懂的.
至于View中的(1)内部类TransformationInfo; (2)getRotation/getScaleX/getAlpha等getter; (3)setRotation/setScaleX/setAlpha等setter, 读者届时就可以自行理解了.

这篇文章来源自我之前的笔记. 笔记是写给我自己看的, 所以会有很多跳跃和奇怪的名词.

(一)ValueAnimator 和 ObjectAnimator 的原理简介

(1)几个重要的关系简述

属性用: Property<”T”, “V”>
值 用: Keyframe
而 PropertyValuesHolder 表示:

其一:
    一个 Property<T, V>  所对应的 一系列: Keyframe.
    存放在 一个 集合中: KeyframeSet mKeyframeSet
    每一个 Keyframe, 就是  key---values.
    一个key, 一系列 values.
    ----指这个key在不同时刻的value
其二:
    其中有一个 域:
        private Object mAnimatedValue;
    表示 当前时刻 的值.
    其是通过 如下方法 计算出来的:
        void calculateValue(float fraction)
    通过 如下方法 取出 这个值:
        Object getAnimatedValue()

    ValueAnimator 中有一个 方法:
        Object getAnimatedValue()
            可以取出 当前 时刻 对应的 所有的 PropertyValuesHolder 中的 mAnimatedValue 的值.
        Object getAnimatedValue(String propertyName) 
            取出 当前时刻, 指定的 PropertyValuesHolder 中的 mAnimatedValue 的值.
    在用 ValueAnimator 实现 属性动画时, 
        因为 没有传入 对象, 而只传入 属性/一系列值/变化规律(TypeEvaluator), 
            所以 不会执行到 getter 和 setter, 
    但 我们可以 为其 注册一个 AnimatorUpdateListener 监听器, 其中有一个方法:
        void onAnimationUpdate(ValueAnimator animation);
    我们 通过其 参数的 ValueAnimator对象的 getAnimatedValue 来得到 当前 动画的值.
    ----这个 就是 ValueAnimator 的原理.

好吧: 实际上 PropertyValuesHolder 就是 一个 计算器.

(2)ValueAnimator 并未与 具体对象 关联.

其中 含有 多个 PropertyValuesHolder.
即, 多个属性, 
        其中, 每一个属性: key--values对.
ValueAnimator 并没有 和 具体的 对象 绑定, 所以 动画时, 其不会调用 对象的 getter 和 setter.
----ValueAnimator 的原理是: 我们一开始传入一些值, 以及 规定了变化规律(TypeEvaluator),
      在动画 播放 的过程中, 其会计算出 当前这个时刻的 值 是多少.      
      然后 可以通过 注册上的 AnimatorUpdateListener 监听器中的: 
         void onAnimationUpdate(ValueAnimator animation);
      调用参数 的 ValueAnimator 对象的 getAnimatedValue 方法, 
          来获得 当前时刻的值.
      然后 在这里, 我们根据这个 值, 来对 ui进行更新.

(3)ObjectAnimator 之所以 称为 ObjectAnimator, 是因为 其我们 会传入 这个 object

有了 object + 属性 + 变化规律, 这样 当时间变化时, 对应的 动画值 发生变化时, 我们通过 setter 来进行处理.
如果 object 类型的 setter 方法中, 有进行 ui更新的话, 那就显示出了动画效果.
这里的关键就是:  ObjectAnimator 复写  animateValue 方法.
----在这个 animateValue 方法中, 执行完 super.animateValue 方法后, 执行 mValues[i].setAnimatedValue(mTarget); , 
即 执行了 object 的 setter方法.

(4)以上 就是 ValueAnimator 和 ObjectAnimator 的原理.

—-具体 请参见, 我做在 SDK_API_16 源代码 中的 笔记.

列一下 这个 结构:

(5)另外, 这里涉及两个 监听器:

(1)Animator.AnimatorListener:
    public static interface AnimatorListener {
        void onAnimationStart(Animator animation);
        void onAnimationEnd(Animator animation);
        void onAnimationCancel(Animator animation);
        void onAnimationRepeat(Animator animation);
    }
(2)ValueAnimator.AnimatorUpdateListener 
    public static interface AnimatorUpdateListener {
        void onAnimationUpdate(ValueAnimator animation);
    }

(二)下面 讲一些 与 这个 属性动画 相关的 一些类:

—-要看属性动画的源码, 首先要搞明白这些类:

(1)Property<”K”, “V”>

不与具体对象绑定, 与具体的值无关.

Property<”K”, “V”>: 宿主类型 T, 属性类型 V
全称: android.util.Property<”K”, “V”>
抽象类, 其有一个子类: ReflectiveProperty, 但程序员都用不了的.

(1)其中两个数据成员:

private final String mName;      //属性的名称.
private final Class<"V"> mType;    //属性的类型----Class对象

(2)方法有:
a)静态方法:

static <T, V> Property<T, V> of(Class<T> hostType, Class<V> valueType, String name)
                即, 创建一个 Property对象.
                    参数一: Class<T> hostType   ----宿主类型
                    参数二: Class<V> valueType  ----属性类型
                    参数三: String name         ----属性名称.
                其内部实际上是:
                    new ReflectiveProperty<T, V>(hostType, valueType, name);

b)一般方法:
最重要这两个:

void set(T object, V value) 
    ----对 设置 object这个对象中的 这个Property对应的 值 为 value.
V get(T object);
    ----即 取出 object这个对象中的 这个Property对应的 值.
        执行 这两个方法时, 会执行到 object 的 setter 和 getter 的.

然后:

String getName()
Class<V> getType() 
boolean isReadOnly()

简而言之, 这里 其实就是一个反射的处理.

(2)Keyframe

全称: android.animation.Keyframe
抽象类, 有很多种子类.比如 这个 Keyframe 类中 就定义了一些内部类: ObjectKeyframe / IntKeyframe / FloatKeyframe.

用于表示 一个键值对: 某一个时刻, 对应的 值是多少.
—-这个用于动画中的.

其有几个 关键的 数据成员:

float mFraction;           //指时刻----用 0-1 之间的数 来表示
int mValue;                //这个 是其子类 定义的, 比如 IntKeyframe 会定义一个 这样的属性
Class mValueType;
boolean mHasValue = false;

静态方法:

static Keyframe ofInt(float fraction, int value)
static Keyframe ofInt(float fraction)   ----值默认为 0

static Keyframe ofFloat(float fraction, float value) 
static Keyframe ofFloat(float fraction)  ----值默认为 0

static Keyframe ofObject(float fraction, Object value)
static Keyframe ofObject(float fraction)  ----值默认为 null

一般方法:

boolean hasValue()

Object getValue()                    获得值
void setValue(Object value)          设置值

float getFraction()                  获得时刻
void setFraction(float fraction)     设置时刻

TimeInterpolator getInterpolator() 
void setInterpolator(TimeInterpolator interpolator)

Class getType()

(3)TypeEvaluator 和 Interpolator(TimeInterpolator)

(a)Interpolator(TimeInterpolator):

表示的是: 时刻 —- 变化程度.
即, float—-float 关系, 即 参数 和 返回 值 都是 [0,1] 范围内的.
(1)参数 为 时刻
(2)返回 为 变化程序.

public interface TimeInterpolator {
    float getInterpolation(float input);
}

(b)TypeEvaluator:

表示的 能力 大大优于 Interpolator.
—-即, 返回值的 类型 不仅仅可以是 int/float/.etc 的基类类型, 也可以是 对象类型.
(1)参数: 进去的是 时刻, 以及 返回结果的 起始值—-以便于 返回值 进行参考.
(2)返回值: 根据 时刻, startValue, endValue 去算出来.

public interface TypeEvaluator<T> {
    public T evaluate(float fraction, T startValue, T endValue);
}

这个在 属性动画 里 很有用.
—-因为 属性动画 对应的是 属性
—-属性 可能是任意一种类型的.
—-我们通常只是 给定一个 T startValue, T endValue, 和 durationTime,
对于 数据类型的属性, 其变化 就用这个 来处理吧.
—-即, 方便了 我们去设置 自定义属性.

举例:
sdk中 已存在 的 三个子类:

    ArgbEvaluator
    FloatEvaluator
    IntEvaluator

都是线性的.

如下所示:

public class ArgbEvaluator implements TypeEvaluator {

    public Object evaluate(float fraction, Object startValue, Object endValue) {
        int startInt = (Integer) startValue;
        int startA = (startInt >> 24);
        int startR = (startInt >> 16) & 0xff;
        int startG = (startInt >> 8) & 0xff;
        int startB = startInt & 0xff;

        int endInt = (Integer) endValue;
        int endA = (endInt >> 24);
        int endR = (endInt >> 16) & 0xff;
        int endG = (endInt >> 8) & 0xff;
        int endB = endInt & 0xff;

        return (int)((startA + (int)(fraction * (endA - startA))) << 24) |
                (int)((startR + (int)(fraction * (endR - startR))) << 16) |
                (int)((startG + (int)(fraction * (endG - startG))) << 8) |
                (int)((startB + (int)(fraction * (endB - startB))));
    }
}

public class FloatEvaluator implements TypeEvaluator<Number> {
    public Float evaluate(float fraction, Number startValue, Number endValue) {
        float startFloat = startValue.floatValue();
        return startFloat + fraction * (endValue.floatValue() - startFloat);
    }
}

public class IntEvaluator implements TypeEvaluator<Integer> {
    public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
        int startInt = startValue;
        return (int)(startInt + fraction * (endValue - startInt));
    }
}

(4)PropertyValuesHolder

全称: android.animation.PropertyValuesHolder

PropertyValuesHolder 对象 含 有几个方面:
(1)属性 —- 用 Property 或者 String 来表示.
(2)与此属性 对应的 一系列值.
—-其 并没有 指定 与这个属性相关联的 某个具体的对象.

静态方法: —-即用于 创建 PropertyValuesHolder 对象.

static PropertyValuesHolder ofInt(String propertyName, int... values)
static PropertyValuesHolder ofInt(Property<?, Integer> property, int... values)

static PropertyValuesHolder ofFloat(String propertyName, float... values) 
static PropertyValuesHolder ofFloat(Property<?, Float> property, float... values)

static     PropertyValuesHolder ofObject(String propertyName, TypeEvaluator evaluator, Object... values)
static <V> PropertyValuesHolder ofObject(Property property, TypeEvaluator<V> evaluator, V... values)
                    这里 还可以 加上用 TypeEvaluator 来处理.
                    ----即, 在什么时候返回什么样的 属性值.

static PropertyValuesHolder ofKeyframe(String propertyName, Keyframe... values)
static PropertyValuesHolder ofKeyframe(Property property, Keyframe... values)
                    这里 还加上 Keyframe 来处理.
                    ----即, 表示 这个属性的 一系列 时刻-值 键值对
                    ----即, 在什么时候返回什么样的 属性值.

一般方法:

void setProperty(Property property)
void setPropertyName(String propertyName)
String getPropertyName()

void setIntValues(int... values) 
void setFloatValues(float... values)
void setKeyframes(Keyframe... values)
void setObjectValues(Object... values)

void setEvaluator(TypeEvaluator evaluator)

标签: android

热门推荐