Android属性动画赏析,Android属性动画源码分析(三)

本文详细剖析了Android属性动画中FloatPropertyValuesHolder的创建过程,包括如何生成关键帧KeyFrameSet,以及关键帧如何根据传入值动态构建动画路径。理解关键帧对于动画执行至关重要,本文还揭示了动画变化方向和关键帧集合的作用。

在上一篇文章中,我们对ObjectAnimator.ofFloat方法进行了分析,其中生成PropertyValuesHolder对象的方法PropertyValuesHolder.ofFloat("", values)我们并没有进去看,这一篇我们就看看这个"holder"生成的时候究竟做了什么事。

首先我们进入ObjectAnimator.ofFloat方法:

//PropertyValuesHolder.java

public static PropertyValuesHolder ofFloat(String propertyName, float... values) {

return new FloatPropertyValuesHolder(propertyName, values);

}

这里新建了一个FloatPropertyValuesHolder,类似于工厂模式,对不同的需要产生不同类型的PropertyValuesHolder对象,可以是int,float或者其他对象类型(提供了转换器),我们这里不做细致研究,还是沿着主线路往下看:

//FloatPropertyValuesHolder.java

public FloatPropertyValuesHolder(String propertyName, float... values) {

super(propertyName);

setFloatValues(values);

}

...

//PropertyValuesHolder.java

//super(propertyName)进了这里

private PropertyValuesHolder(String propertyName) {

mPropertyName = propertyName;

}

...

//FloatPropertyValuesHolder.java

//setFloatValues(values)走了这里

@Override

public void setFloatValues(float... values) {

super.setFloatValues(values);

mFloatKeyframes = (Keyframes.FloatKeyframes) mKeyframes;

}

这里主要讲属性名保存了起来,并且设置了一个"KeyFrameSet",即关键帧集合,很明显,关键帧的生成代码就在super.setFloatValues(values)里,我们进去在一探究竟:

//PropertyValuesHolder.java

public void setFloatValues(float... values) {

mValueType = float.class;

mKeyframes = KeyframeSet.ofFloat(values);

}

这个keyframeSet的构建形式和PropertyValuesHolder的形式看起来类似,当然,实际也是如此:

//KeyFrameSet.java

public static KeyframeSet ofFloat(float... values) {

boolean badValue = false;

int numKeyframes = values.length;

FloatKeyframe keyframes[] = new FloatKeyframe[Math.max(numKeyframes,2)];

if (numKeyframes == 1) {

keyframes[0] = (FloatKeyframe) Keyframe.ofFloat(0f);

keyframes[1] = (FloatKeyframe) Keyframe.ofFloat(1f, values[0]);

if (Float.isNaN(values[0])) {

badValue = true;

}

} else {

keyframes[0] = (FloatKeyframe) Keyframe.ofFloat(0f, values[0]);

for (int i = 1; i < numKeyframes; ++i) {

keyframes[i] =

(FloatKeyframe) Keyframe.ofFloat((float) i / (numKeyframes - 1), values[i]);

if (Float.isNaN(values[i])) {

badValue = true;

}

}

}

if (badValue) {

Log.w("Animator", "Bad value (NaN) in float animator");

}

return new FloatKeyframeSet(keyframes);

}

我们看到这段代码的大体作用是根据规则生成了一系列的KeyFrames()关键帧),并且将其添加到了KeyFrameSet(即关键帧集合),那么这个关键帧是什么呢,参照官方说法:

//KeyFrames.java

/**

* This class holds a time/value pair for an animation. The Keyframe class is used

* by {@link ValueAnimator} to define the values that the animation target will have over the course

* of the animation. As the time proceeds from one keyframe to the other, the value of the

* target object will animate between the value at the previous keyframe and the value at the

* next keyframe.

*...

*/

按照官方的说法,KeyFrames是一个保存动画中时间/值的键值对,用于定义动画目标进行过程中的过程值。要进行动画的目标将会依照这些KeyFrames进行动画。

通俗一点的说,比如最终有三个KeyFrames,第一个是0.0,值是100,第二个是0.5,值是200,第三个是是1.0,值是300;动画目标就会根据这个KeyFrames在最开始的时候得到100的值,在时间进行到一半的时候得到200的值,在时间结束的时候获得300的值。其实KeyFrames就是代表了动画进行的关键帧数,为动画的实际执行提供了“变化的方向”, 而KeyFramesSet代表了动画进行的关键帧数集合。了解了这些,我们在回来分析下KeyFrameSet.ofFloat的代码:

首先我们知道传入的参数是我们之前的变化的一系列值,例如在最开始的示例中,我们传入的是0.8f,1.0f;然后int numKeyframes = values.length;记录了传入值的数量,接下来生成了一个KeyFrames的数组(最终这个数组用于初始化KeyFrameSet),该数组的最小值为2,也就代表着最小要有两个值来控制这次变化。之后是一个判断,用于判断当前传入值的数量是1还是大于1,如果是1的话

keyframes[0] = (FloatKeyframe) Keyframe.ofFloat(0f);

keyframes[1] = (FloatKeyframe) Keyframe.ofFloat(1f, values[0]);

就通过这两句生成一个从0到values[0]变化的帧,如果大于1(小于1不会到这里),则根据numKeyframes ,来生成numKeyFrames个帧,每个帧的进度都是通过当前帧的位置/帧的总数来平均分:

keyframes[i] =(FloatKeyframe) Keyframe.ofFloat((float) i / (numKeyframes - 1), values[i]);

(在这个过程中,如果传入的值不符合条件,会记录一个badValues标志代表本次的值有问题)

if (Float.isNaN(values[i])) {

badValue = true;

}

最终,将生成的所有KeyFrames放到KeyFramesSet中进行保存,然后将这个set存放到mFloatKeyframes中。

我们在贴出Keyframe.ofFloat();的实现,也是个初始化的过程:

FloatKeyframe(float fraction, float value) {

mFraction = fraction;

mValue = value;

mValueType = float.class;

mHasValue = true;

}

至此,我们就把属性动画的初始化过程看完了,总体理下来我们可以看出大体的初始化过程如下:

ObjectAnimation.ofFloat->传递要进行动画的对象,要改变的属性名,一系列的属性值

属性名+属性值存放到了PropertyValueHolder中,这个用来代表一个属性的变化情况

如果初始化时使用ObjectAnimation.ofPropertyValuesHolder则相当于多个属性的变化情况(类似于动画集合的效果)

PropertyValues.setValues()->进行变化值的设置,生成关于这系列值的关键帧

mKeyframes ->该PropertyValues中变化值生成的关键帧集合

下一篇文章我们将开始分析属性动画start的过程。

其他部分链接

[Android属性动画源码分析(一)]

[Android属性动画源码分析(二)]

[Android属性动画源码分析(四)]

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值