安卓属性动画进阶PropertyValuesHolder与Keyframe
- 可能大家都注意到了在ObjectAnimator和ValueAnimator中还有一个创建实例的方法ofPropertyValuesHolder()
- 因为ObjectAnimator是继承自ValueAnimator的,我们就来学习一下ObjectAnimator.ofPropertyValuesHolder()吧,ValueAnimator的使用也类似
- 这里说一下ofInt和其他一些of方法,他们在得到我们设置的参数之后,将我们这些参数进行包装成一个PropertyValuesHolder类实例,也就是说,这个类实例保存着我们这个动画的一些基本属性,我们在操动画的时候,其实就是操作这个类实例的
- 那么到这里我们也就明白ofPropertyValuesHolder()这个方法的用处了吧,他让我们自己去构建自己的动画PropertyValuesHolder实例
public static ObjectAnimator ofPropertyValuesHolder(Object target,PropertyValuesHolder... values)
PropertyValuesHolder
- 根据官方文档以及源码,这个类并没有向我们外放公开的构造方法,而是提供了一系列的生成类实例的静态方法,有兴趣可以去看官方文档,这里只简单说一下几个常用的
静态方法 |
方法说明 |
public static PropertyValuesHolder ofFloat(String propertyName, float... values) |
构造并返回一个PropertyValuesHolder,其中包含一个给定的属性名称和一组浮点值。 |
public static PropertyValuesHolder ofInt(String propertyName, int... values) |
构造并返回一个具有给定属性名称和一组int值的PropertyValuesHolder。 |
public static PropertyValuesHolder ofObject(String propertyName, TypeEvaluator evaluator,Object... values) |
构造并返回一个PropertyValuesHolder,其中包含一个给定的属性名称和一组Object值。 |
public static PropertyValuesHolder ofKeyframe(String propertyName, Keyframe... values) |
构造并返回一个PropertyValuesHolder对象,其中包含指定的属性名称和一组值。 |
- 可以看到,在每个参数中基本都包括,要改变的属性名,和几组区间值,在给大家看一下第一个方法的源码
public static PropertyValuesHolder ofFloat(String propertyName, float... values) {
return new FloatPropertyValuesHolder(propertyName, values);
}
- 他返回了一个PropertyValuesHolder的子类FloatPropertyValuesHolder,同理,在ofInt或者其他方法时也是返回不同类型的子类,这些个子类其实是PropertyValuesHolder的内部类,再跟进去看一下这个子类的参数吧
private static final HashMap<Class, HashMap<String, Long>> sJNISetterPropertyMap =
new HashMap<Class, HashMap<String, Long>>();
long mJniSetter;
private FloatProperty mFloatProperty;
Keyframes.FloatKeyframes mFloatKeyframes;
float mFloatAnimatedValue;
- 我这里把子类的所有参数放在这里,可以推测,他应该是通过那个Map来保存我们传进去的各个参数的,前面的class应该就是通过反射来拿到目标控件的set或者get方法的,到这里也就差不多了
- 再结合
public static ObjectAnimator ofPropertyValuesHolder(Object target,PropertyValuesHolder... values)
- 应该大概猜到这个方法是干什么用的了吧,他就跟我们之前讨论过的补间动画的set一样,把好多个动画包装起来,拿给一个控件用,于是就可以实现控件的多元化动画了
- 看一下大概使用方法吧
PropertyValuesHolder rotationHolder = PropertyValuesHolder.ofFloat("Rotation", 60f, -60f, 40f, -40f, -20f, 20f, 10f, -10f, 0f);
PropertyValuesHolder colorHolder = PropertyValuesHolder.ofInt("BackgroundColor", 0xffffffff, 0xffff00ff, 0xffffff00, 0xffffffff);
ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(mTextView, rotationHolder, colorHolder);
animator.setDuration(3000);
animator.setInterpolator(new AccelerateInterpolator());
animator.start();
- 不用解释,大家都明白
- 对于PropertyValuesHolder还有ofObject创建动画的方法,其实还是将控制权交给了我们,用法都大同小异
- 在看到动画包装类的参数的时候,大家有没有注意到Keyframes呢,谷歌为了方便我们控制动画速率,而不是每次去麻烦的自己写插值器,就为我们这些渣渣提供了这个类
- 接下来看这个类
Keyframe
- 我们在定义动画的时候,往往是指定几个定值,表示某个View的某个属性从一个值变到后值,那么这个keyframe表示的就是这个,不过他加上了时间这个概念,先看一下构造吧
public static Keyframe ofFloat(float fraction, float value)
- fraction:表示当前的显示进度,即从加速器中getInterpolation()函数的返回值;
- value:表示当前应该在的位置
- 明白了吧,通过这样我们可以很轻松的控制动画的快慢
- 那么我们需要怎么使用我们自己定义的时间值呢
- 放心吧,安卓已经为我们弄好了,在动画的生成实例类中,有这么一个方法
public static PropertyValuesHolder ofKeyframe(String propertyName, Keyframe... values)
- 嗯,为VIew中属性名叫这个(propertyName)那个属性按照我为你设置的规则(Keyframe)这么改变他的值
- 看一下具体代码
Button button = findViewById(R.id.main_useKeyFrameViewBt)
ImageView imageView = findViewById(R.id.main_useKeyFrameViewIv)
Keyframe keyframe = Keyframe.ofFloat(0,0)
Keyframe keyframe0 = Keyframe.ofFloat(0.3f,-200)
Keyframe keyframe1 = Keyframe.ofFloat(0.5f,200)
Keyframe keyframe2 = Keyframe.ofFloat(1f,100)
PropertyValuesHolder holder = PropertyValuesHolder.ofKeyframe("translationY",keyframe,keyframe0
,keyframe1,keyframe2)
final ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(imageView,holder)
animator.setDuration(3000)
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
animator.start()
}
})
- 代码很简单,就是来回上下平移,不过移动的速度不同,理解用法即可
- 说到这里,我将平时用的几个系统自带的属性列一下
alpha,rotation,rotationX,rotationY,translationX,translationY,scaleX,scaleY
- 注意这里使用的还是驼峰命名法,大家在使用的时候或者自己定义属性的时候一定要注意
- 那么到这里,关于这个就介绍完了,在valueAnimator其实也是一样的,可以类比