本学习笔记主要来自启舰:
http://blog.csdn.net/harvic880925/article/details/50752838
在学习过程中融入了自己的理解和思路。
前面掌握了ValueAnimator、ObjectAnimator动画通过通过ofInt(), ofFloat(), ofObject()等方式创建实例,实际上动画实例的创建还有另外的方法:
//valueAnimator的
public ValueAnimator ofPropertyValuesHolder(PropertyValuesHolder... values){
}
// ObjectAnimator的
public ObjectAnimator ofPropertyValuesHolder(Object target,PropValueHolder... values){
}
也就是说ValueAnimator和ObjectAnimator除了通过ofInt(), ofFloat(), ofObject()创建实例外,还都有一个ofPropertyValuesHolder()方法来创建实例,这篇文章我就带大家来看看如何通过ofPropertyValuesHolder()来创建实例的。
由于ValueAnimator和ObjectAnimator都具有ofPropertyValuesHolder()函数,使用方法也差不多,相比而言,ValueAnimator的使用机会不多,这里我们就只讲ObjectAnimator中ofPropertyValuesHolder()的用法。相信大家懂了这篇以后,再去看ValueAnimator的ofPropertyValuesHolder(),也应该是会用的。
一、PropertyValuesHolder
1、概述
PropertyValuesHolder的意义是:它其中保存了动画过程中所需要操作的属性和对应的值。我们通过ofFloat(Object target, String propertyName, float… values)构造的动画,ofFloat()的内部实现其实就是将传进来的参数封装成PropertyValuesHolder实例来保存动画状态。在封装成PropertyValuesHolder实例以后,后期的各种操作也是以PropertyValuesHolder为主。
PropertyValuesHolder中有很多函数,有些函数的api等级是11,有些函数的api等级是14和21; 高api的函数我们就不讲了,只讲讲api 11的函数的用法。
首先,我们来看看创建实例的函数:
public PropertyValuesHolder ofFloat(String propertyName, float... values){}
public PropertyValuesHolder ofInt(String propertyName, int... values){}
public PropertyValuesHolder ofObject(String propertyName, TypeEvaluator evaluator,Object... values){}
public PropertyValuesHolder ofKeyframe(String propertyName, Keyframe... values){}
这一段我们着重讲ofFloat、ofInt和ofObject的用法,ofKeyframe我们单独讲。
2、PropertyValuesHolder之ofFloat()、ofInt()
(1)ofFloat()、ofInt():
我们先来看看它们的构造函数:
public static PropertyValuesHolder ofFloat(String propertyName, float... values){}
public static PropertyValuesHolder ofInt(String propertyName, int... values){}
propertyName:表示ObjectAnimator需要操作的属性名。即ObjectAnimator需要通过反射查找对应属性的setProperty()函数的那个property.
values:属性所对应的参数,同样是可变长参数,可以指定多个,还记得我们在ObjectAnimator中讲过,如果只指定了一个,那么ObjectAnimator会通过查找getProperty()方法来获得初始值。
(2)、ObjectAnimator.ofPropertyValuesHolder()
public static ObjectAnimator ofPropertyValuesHolder(Object target,PropertyValuesHolder... values){}
target:指需要执行动画的控件;
values:是一个可变长参数,可以传进去多个PropertyValuesHolder实例,由于每个PropertyValuesHolder实例都会针对一个属性做动画,所以如果传进去多个PropertyValuesHolder实例,将会对控件的多个属性同时做动画操作。
下面我们就举个例子来说明如何通过PropertyValuesHolder的ofFloat、ofInt来做动画。
private void doPropertyAnimator() {
PropertyValuesHolder holder = PropertyValuesHolder.ofFloat("Rotation",
60f, -60f, 50f, -50f, -40f, 40f, 30f, -30f, 20f, -20f, 10f, -10f, 0f);
PropertyValuesHolder holderColor = PropertyValuesHolder.ofInt(
"BackgroundColor", 0xfffffff0, 0xffff00ff, 0xffffff00, 0xffffff0f);
objectAnimator = ObjectAnimator.ofPropertyValuesHolder(
mFlAnimator, holder, holderColor);
objectAnimator.setDuration(500);
objectAnimator.setRepeatMode(ValueAnimator.REVERSE);
objectAnimator.setRepeatCount(ValueAnimator.INFINITE);
objectAnimator.setInterpolator(new LinearInterpolator());
objectAnimator.start();
}
其中,mFlAnimator是自定义TextView(ObjTextView)在xml中的布局,ObjTextView如下:
public class ObjTextView extends TextView {
public ObjTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setCharText(Character character){
setText(String.valueOf(character));
}
}
Holder对象设定了动画旋转的角度,holderColor对象设定了动画的背景色变化,objectAnimator动画对象里面添加了target控件对象及可变参数Holder和holderColor,当然我们还可以在这里添加别的参数,比如透明度(alpha)的变化,缩放(scale)等动画效果。
3、PropertyValuesHolder之ofObject()
(1)、概述
我们先来看一下ofObject的构造函数:
public static PropertyValuesHolder ofObject(String propertyName,
TypeEvaluator evaluator, Object... values);
参数的含义,再次不多说,不懂的话就找根面条上吊得了。
(2)、示例
public class CharEvaluator implements TypeEvaluator<Character> {
@Override
public Character evaluate(float v, Character character, Character t1) {
int start = (int)character;
int end = (int)t1;
char cha = (char)value;
return cha;
}
}
这段代码简单,前面也已经讲解过很多次了,不多说,不懂的话就找根面条上吊得了。
public class ObjTextView extends TextView {
public ObjTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setCharText(Character character){
setText(String.valueOf(character));
}
}
从CharEvaluator中可以看出,从CharEvaluator中产出的动画中间值类型为Character类型。TextView中虽然有setText(CharSequence text) 函数,但这个函数的参数类型是CharSequence,而不是Character类型。所以我们要自定义一个类派生自TextView来改变TextView的字符:
public class ObjTextView extends TextView {
public ObjTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setCharText(Character character){
setText(String.valueOf(character));
}
}
这个与之前上面的相同。
动画的代码如下:
private void doPropertyObjAnimator() {
PropertyValuesHolder holderText = PropertyValuesHolder.ofObject(
"CharText", new CharEvaluator(), new Character('A'), new Character('Z'));
PropertyValuesHolder holder = PropertyValuesHolder.ofFloat(
"Rotation", 60f, -60f, 50f, -50f, -40f, 40f, 30f, -30f, 20f,
-20f, 10f, -10f, 0f);
PropertyValuesHolder holderColor = PropertyValuesHolder.ofInt(
"BackgroundColor", 0xfffffff0, 0xffff00ff, 0xffffff00, 0xffffff0f);
objectAnimator01 = ObjectAnimator.ofPropertyValuesHolder(
mFlAnimator, holderText, holder, holderColor);
objectAnimator01.setDuration(2000);
objectAnimator01.setInterpolator(new LinearInterpolator());
objectAnimator01.setRepeatCount(ValueAnimator.INFINITE);
objectAnimator01.setRepeatMode(ValueAnimator.REVERSE);
objectAnimator01.start();
}
首先是根据PropertyValuesHolder.ofObject生成一个PropertyValuesHolder实例,注意它的属性就是CharText,所对应的set函数就是setCharText,由于CharEvaluator的中间值是Character类型,所以CharText属性所对应的完整的函数声明为setCharText(Character character);这也就是我们为什么要自定义一个MyTextView原因,就是因为TextView中没有setText(Character character)这样的函数。
二、Keyframe
1、概述:KeyFrame直译过来就是关键帧。 一个关键帧必须包含两个原素,第一时间点,第二位置。即这个关键帧是表示的是某个物体在哪个时间点应该在哪个位置上。
KeyFrame的生成方式为:
Keyframe kf0 = Keyframe.ofFloat(0, 0);
Keyframe kf1 = Keyframe.ofFloat(0.1f, -20f);
Keyframe kf2 = Keyframe.ofFloat(1f, 0);
上面生成了三个KeyFrame对象,其中KeyFrame的ofInt函数的声明为:
public static Keyframe ofFloat(float fraction, float value);
fraction:表示当前的显示进度,即从加速器中getInterpolation()函数的返回值;
value:表示当前应该在的位置
比如Keyframe.ofFloat(0, 0)表示动画进度为0时,动画所在的数值位置为0;Keyframe.ofFloat(0.25f, -20f)表示动画进度为25%时,动画所在的数值位置为-20;Keyframe.ofFloat(1f,0)表示动画结束时,动画所在的数值位置为0;
在理解了KeyFrame.ofFloat()的参数以后,我们来看看PropertyValuesHolder是如何使用KeyFrame对象的:
public static PropertyValuesHolder ofKeyframe(String propertyName, Keyframe... values);
fraction:表示当前的显示进度,即从加速器中getInterpolation()函数的返回值;
value:表示当前应该在的位置
PropertyValuesHolder frameHolder =
PropertyValuesHolder.ofKeyframe(
"rotation", frame0, frame1, frame2);
mImage, frameHolder);
animator.setDuration(1000);
animator.start();
2、示例:
private void doOfFloatAnim(){
Keyframe frame0 = Keyframe.ofFloat(0f, 0);
Keyframe frame1= Keyframe.ofFloat(0.1f, -20f);
Keyframe frame2 = Keyframe.ofFloat(0.2f, 20f);
Keyframe frame3 = Keyframe.ofFloat(0.3f, -20f);
Keyframe frame4 = Keyframe.ofFloat(0.4f, 20f);
Keyframe frame5 = Keyframe.ofFloat(0.5f, -20f);
Keyframe frame6 = Keyframe.ofFloat(0.6f, 20f);
Keyframe frame7 = Keyframe.ofFloat(0.7f, -20f);
Keyframe frame8 = Keyframe.ofFloat(0.8f, 20f);
Keyframe frame9 = Keyframe.ofFloat(0.9f, -20f);
Keyframe frame10 = Keyframe.ofFloat(1, 0);
frameHolder = PropertyValuesHolder.ofKeyframe("rotation",
frame0, frame1, frame2, frame3, frame4, frame5,
frame6, frame7, frame8, frame9, frame10);
frameHolder.setEvaluator(new CharEvaluator());
animator = ObjectAnimator.ofPropertyValuesHolder(
mIvKeyframe, frameHolder);
animator.setDuration(500);
animator.setInterpolator(new LinearInterpolator());
animator.start();
}
3、Keyframe之ofFloat、ofInt与常用函数
(1)、ofFloat、ofInt
其实Keyframe除了ofFloat()以外,还有ofInt()、ofObject()这些创建Keyframe实例的方法,Keyframe.ofObject()我们下部分再讲,这部分,我们着重看看ofFloat与ofInt的构造函数与使用方法:
public static Keyframe ofFloat(float fraction)
public static Keyframe ofFloat(float fraction, float value)
public static Keyframe ofInt(float fraction)
public static Keyframe ofInt(float fraction, int value)
2)、常用函数:
//设置fraction参数,即Keyframe所对应的进度;
public void setFraction(float fraction)
// 设置当前Keyframe所对应的值;
public void setValue(Object value)
// 设置Keyframe动作期间插值器;
public void setInterpolator(TimeInterpolator interpolator)
这三个函数中,插值器的作用应该是比较难理解,如果给这个Keyframe设置上插值器,那么这个插值器就是从上一个Keyframe开始到当前设置插值器的Keyframe时,这个过程值的计算是利用这个插值器的,比如:
Keyframe frame0 = Keyframe.ofFloat(0f, 0);
Keyframe frame1 = Keyframe.ofFloat(0.1f, -20f);
frame1.setInterpolator(new BounceInterpolator());
Keyframe frame2 = Keyframe.ofFloat(1f, 20f);
frame2.setInterpolator(new LinearInterpolator());
在上面的代码中,我们给frame1设置了插值器BounceInterpolator,那么在frame0到frame1的中间值计算过程中,就是用的就是回弹插值器;
同样,我们给frame2设置了线性插值器(LinearInterpolator),所以在frame1到frame2的中间值计算过程中,使用的就是线性插值器。很显然,给Keyframe.ofFloat(0f, 0)设置插值器是无效的,因为它是第一帧。
4、Keyframe之ofObject
与ofInt,ofFloat一样,ofObject也有两个构造函数:
public static Keyframe ofObject(float fraction);
public static Keyframe ofObject(float fraction, Object value);
同样,如果使用ofObject(float fraction)来构造,也必须使用setValue(Object value)来设置这个关键帧所对应的值。我们还以TextView更改字母的例子来使用下Keyframe.ofObject.
private void doKeyframeofObject(){
Keyframe frame0 = Keyframe.ofObject(0f, new Character('A'));
Keyframe frame1 = Keyframe.ofObject(0.1f, new Character('L'));
Keyframe frame2 = Keyframe.ofObject(1,new Character('Z'));
frameHolder02 = PropertyValuesHolder.ofKeyframe(
"CharText",frame0,frame1,frame2);
frameHolder02.setEvaluator(new CharEvaluator());
animator02 = ObjectAnimator.ofPropertyValuesHolder(
mFlAnimator, frameHolder);
animator02.setDuration(3000);
animator02.start();
}
利用关键帧创建PropertyValuesHolder后,一定要记得设置自定义的Evaluator:
frameHolder02.setEvaluator(new CharEvaluator());
凡是使用ofObject来做动画的时候,都必须调用frameHolder.setEvaluator显示设置Evaluator,因为系统根本是无法知道,你动画的中间值Object真正是什么类型的。
如果去掉第0帧,将以第一个关键帧为起始位置
如果去掉结束帧,将以最后一个关键帧为结束位置
使用Keyframe来构建动画,至少要有两个或两个以上帧
三、PropertyValuesHolder的其它函数
// 设置动画的Evaluator
public void setEvaluator(TypeEvaluator evaluator);
// 用于设置ofFloat所对应的动画值列表
public void setFloatValues(float... values);
// 用于设置ofInt所对应的动画值列表
public void setIntValues(int... values);
// 用于设置ofKeyframe所对应的动画值列表
public void setKeyframes(Keyframe... values);
// 用于设置ofObject所对应的动画值列表
public void setObjectValues(Object... values);
// 设置动画属性名
public void setPropertyName(String propertyName);
这些函数都比较好理解。
如果是利用PropertyValuesHolder.ofObject()来创建动画实例的话,我们是一定要显示调用 PropertyValuesHolder.setEvaluator()来设置Evaluator的。谨记!谨记!!谨记!!!