属性动画:PropertyValuesHolder
前面属性动画学习的过程中,在ValueAnimator中提到过ValueAnimator.ofPropertyValuesHolder(PropertyValuesHolder... values)构造方法(详见《属性动画:ValueAnimator及其监听器》3.1节),还有ObjectAnimator中也提到过ObjectAnimator.ofPropertyValuesHolder (Object target, PropertyValuesHolder... values)方法获取ObjectAnimator属性动画(详见《属性动画:ObjectAnimator基础》3.1节)。
1、PropertyValuesHolder 类
该类自API level 11添加到包android.animation中,通常用来构造属性动画,此外还有Keyframe关键帧类。
PropertyValuesHolder包含有关属性以及在动画过程中该属性应采用的值的信息。PropertyValuesHolder对象可用于通过ValueAnimator或ObjectAnimator创建动画,这些动画可以并行操作多个不同的属性。其实那两个属性动画内部实现也是通过将传入的参数封装成PropertyValuesHolder来保存动画状态,动画的操作也是通过PropertyValuesHolder进行。
2、方法介绍
介绍PropertyValuesHolder类的常用方法。
2.1、构造方法
通过哪些方法可以获取PropertyValuesHolder实例呢?
①ofFloat(String propertyName, float... values):构造并返回具有给定属性和一组浮点值的PropertyValuesHolder
②ofFloat(Property<?, Float> property, float... values)
③ofInt(String propertyName, int... values):构造并返回具有给定属性名称和一组int值的PropertyValuesHolder
④ofInt(Property<?, Integer> property, int... values)
⑥ofKeyframe(String propertyName, Keyframe... values):构造并返回具有指定属性名称和一组值的PropertyValuesHolder对象。这些值可以是任何类型,但是类型应该一致,以便TypeEvaluator可以找到与通用类型匹配的适当值。至少两个关键帧(起始帧、结束帧)
⑦ofKeyframe(Property property, Keyframe... values)
⑧ofMultiFloat(String propertyName, float[][] values):构造并返回具有给定属性名称和一组float[]值的PropertyValuesHolder。float[]必须至少提供两个值,一个开始值和一个结束值。
⑨ofMultiFloat(String propertyName, Path path)
⑩ofMultiFloat(String propertyName, TypeConverter<V, float[]> converter, TypeEvaluator<V> evaluator, V... values)
⑪ofMultiFloat(String propertyName, TypeConverter<T, float[]> converter, TypeEvaluator<T> evaluator, Keyframe... values)
⑫ofMultiInt(String propertyName, int[][] values):构造并返回具有给定属性名称和一组int[]值的PropertyValuesHolder 。int[]必须至少提供两个值,一个开始值和一个结束值。
⑬ofMultiInt(String propertyName, Path path):构造并返回具有给定属性名称的PropertyValuesHolder,以用作多整数设置器。这些值沿路径设置动画,设置器的第一个参数设置为x坐标,第二个参数设置为y坐标。
⑭ofMultiInt(String propertyName, TypeConverter<V, int[]> converter, TypeEvaluator<V> evaluator, V... values)
⑮ofMultiInt(String propertyName, TypeConverter<T, int[]> converter, TypeEvaluator<T> evaluator, Keyframe... values)
⑯ofObject(String propertyName, TypeEvaluator evaluator, Object... values):构造并返回具有给定属性名称和一组Object值的PropertyValuesHolder。由于系统无法在未知类型的对象之间自动插值,因此需要TypeEvaluator。
⑰ofObject(String propertyName, TypeConverter<PointF, ?> converter, Path path)
⑱ofObject(Property property, TypeEvaluator<V> evaluator, V... values)
⑲ofObject(Property<?, V> property, TypeConverter<T, V> converter, TypeEvaluator<T> evaluator, T... values)
⑳ofObject(Property<?, V> property, TypeConverter<PointF, V> converter, Path path)
㉑clone():创建并返回PropertyValuesHolder对象的副本
2.2、getter和setter方法
①getPropertyName():获取动画的属性名称
②setPropertyName(String propertyName):设置动画的属性名称
③setConverter(TypeConverter converter):设置TypeConverter转换器以从值类型转换为设置器的参数类型
④setEvaluator(TypeEvaluator evaluator):TypeEvaluator将根据提供给PropertyValuesHolder的值的类型自动确定。只有float和int类型的值才可以正确插值,所有其他类型都需要设置TypeEvaluator。
⑤setFloatValues(float... values):设置ofFloat()对应动画值列表
⑥setIntValues(int... values):用于设置ofInt()所对应的动画值列表
⑦setKeyframes(Keyframe... values):用于设置ofKeyFrame()所对应的动画值列表
⑧setObjectValues(Object... values):用于设置ofObject()所对应的动画值列表
3、结合属性动画使用
PropertyValuesHolder通常用来构造ObjectAnimator属性动画,因为ObjectAnimator属性动画的构造方法有ObjectAnimator.ofPropertyValuesHolder (Object target, PropertyValuesHolder... values),第二个参数是可变长参数,说明可以传入多个PropertyValuesHolder实例,从而通过一个ObjectAnimator属性动画实现多个维度的动画一起播放。
3.1、使用ofFloat
①ofFloat构造两个PropertyValuesHolder,一个是X轴方向的缩放,效果看起来像是围绕Y轴转动。另一个是透明度属性的PropertyValuesHolder。
PropertyValuesHolder scaleXValuesHolder = PropertyValuesHolder.ofFloat("scaleX", 0f, 1.0f);
PropertyValuesHolder alphaValuesHolder = PropertyValuesHolder.ofFloat("alpha", 0f, 1.0f);②使用PropertyValuesHolder构造属性动画,传入多个PropertyValuesHolder
ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(mImageView, scaleXValuesHolder, alphaValuesHolder);③得到的ObjectAnimator属性动画后面操作和之前的属性动画无异,详见《属性动画:ObjectAnimator基础》
objectAnimator.setDuration(1000);
objectAnimator.start();
3.2、使用ofInt
当尝试想要用ofInt来构造PropertyValuesHolder的时候发现,无论属性传入什么似乎都不行,可能是因为View中setter参数为int的很少。
这倒不难,可以继承View添加以int作为参数的setter方法,内部调用已有的方法即可完成转换。
public class QuibblerImageView extends AppCompatImageView {
...
public void setTranslateX(int x){
setTranslationX(x);
}
public void setTranslateY(int y){
setTranslationY(y);
}
}再使用PropertyValuesHolder的ofInt方法构造实例,设置自定义的TranslateX和TranslateY属性
PropertyValuesHolder translateXValuesHolder = PropertyValuesHolder.ofInt("TranslateX", 100, 200);
PropertyValuesHolder translateYValuesHolder = PropertyValuesHolder.ofInt("TranslateY", 100, 200);
ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(mImageView, translateXValuesHolder, translateYValuesHolder);
objectAnimator.setDuration(1000);
objectAnimator.start();
3.3、使用ofObject
①使用ofObject创建PropertyValuesHolder必须要提供自定义的TypeEvaluator,否则内部无法计算值。
PropertyValuesHolder charValuesHolder = PropertyValuesHolder.ofObject("character", new CharacterEvaluator(), 'a', 'z');
PropertyValuesHolder rotateYValueHolder = PropertyValuesHolder.ofFloat("scaleX", 1f, 0, 1f);
PropertyValuesHolder textColorValue = PropertyValuesHolder.ofObject("textColor",
new ArgbEvaluator(),
Color.parseColor("#1d953f"),
Color.parseColor("#1b315e"));②创建的自定义CharacterEvaluator实现TypeEvaluator接口。关于TypeEvaluator详见《属性动画:TypeEvaluator》。
class CharacterEvaluator implements TypeEvaluator<Character> {
@Override
public Character evaluate(float fraction, Character startValue, Character endValue) {
int begin = (int) startValue;
int end = (int) endValue;
int current = (int) (end - (end - begin) * fraction);
return (char) current;
}
}③至于TextView虽然有setText()方法,但是没有设置Character的setter方法,可以继承TextView添加自定义的setter方法
public class QuibblerTextView extends androidx.appcompat.widget.AppCompatTextView {
public QuibblerTextView(Context context) {
super(context);
}
public QuibblerTextView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public QuibblerTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public void setCharacter(Character character) {
setText(String.valueOf(character));
}
}④使用上面构造完成的3个PropertyValuesHolder创建ObjectAnimator属性动画
ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(mTextView,
charValuesHolder, rotateYValueHolder, textColorValue);
objectAnimator.setDuration(2500);
objectAnimator.start();⑤于是一个属性动画即可完成下面需要三种动画才能实现的“复杂”旋转、内容变换、颜色动画。

相关资料:


