前言:只有比牛人跑的更快,才有可能追上他的脚步。
前几篇给大家讲了ValueAnimator、ObjectAnimator的知识,讲解了它们ofInt(),ofFloat(),ofObject()函数的用法。细心的同学可能会注意到,ValueAnimator、ObjectAnimator除了这些创建Animator实例的方法以外,都还有一个方法:
/** * valueAnimator的 */ public static ValueAnimator ofPropertyValuesHolder(PropertyValuesHolder... values) /** * ObjectAnimator的 */ public static ObjectAnimator ofPropertyValuesHolder(Object target,PropertyValuesHolder... values)也就是说ValueAnimator和ObjectAnimator除了通过ofInt(),ofFloat(),ofObject()创建实例外,还都有一个ofPropertyValuesHolder()方法来创建实例,这篇文章我就带大家来看看如何通过ofPropertyValuesHolder()来创建实例的。
(录的图片效果不好,实际显示时抖的是更厉害的,大家可以看源码效果)
PropertyValuesHolder这个类的意义就是,它其中保存了动画过程中所需要操作的属性和对应的值。我们通过ofFloat(Object target, String propertyName, float… values)构造的动画,ofFloat()的内部实现其实就是将传进来的参数封装成PropertyValuesHolder实例来保存动画状态。在封装成PropertyValuesHolder实例以后,后期的各种操作也是以PropertyValuesHolder为主的。
说到这里,大家就知道这个PropertyValuesHolder是有多有用了吧,上面我们也说了,ObjectAnimator给我们提供了一个口子,让我们自己构造PropertyValuesHolder来构造动画。
public static ObjectAnimator ofPropertyValuesHolder(Object target,PropertyValuesHolder... values)PropertyValuesHolder中有很多函数,有些函数的api等级是11,有些函数的api等级是14和21;
public static PropertyValuesHolder ofFloat(String propertyName, float... values) public static PropertyValuesHolder ofInt(String propertyName, int... values) public static PropertyValuesHolder ofObject(String propertyName, TypeEvaluator evaluator,Object... values) public static PropertyValuesHolder ofKeyframe(String propertyName, Keyframe... values)这里总共有四个创建实例的方法,这一段我们着重讲ofFloat、ofInt和ofObject的用法,ofKeyframe我们单独讲。
public static PropertyValuesHolder ofFloat(String propertyName, float... values) public static PropertyValuesHolder ofInt(String propertyName, int... values)其中:
public static ObjectAnimator ofFloat(Object target, String propertyName, float... values);看到没,在ObjectAnimator.ofFloat中只比PropertyValuesHolder的ofFloat多了一个target,其它都是完全一样的!
public static ObjectAnimator ofPropertyValuesHolder(Object target,PropertyValuesHolder... values)其中:
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实例,第一个rotationHolder:
PropertyValuesHolder rotationHolder = PropertyValuesHolder.ofFloat("Rotation", 60f, -60f, 40f, -40f, -20f, 20f, 10f, -10f, 0f);使用ofFloat函数创建,属性值是Rotation,对应的是View类中SetRotation(float rotation)函数。后面传进去很多值,让其左右摆动。
PropertyValuesHolder colorHolder = PropertyValuesHolder.ofInt("BackgroundColor", 0xffffffff, 0xffff00ff, 0xffffff00, 0xffffffff);这里使用的是ofInt函数创建的,它操作的属性是BackgroundColor,对应的是View类中的setBackgroundColor(int color)函数,后面传进去的16进制颜色值让其在这些颜色值间变化。有关颜色值的变化,大家可以参考《 Animation动画详解(七)——ObjectAnimator基本使用》中第三部分《常用函数》
ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(mTextView, rotationHolder, colorHolder); animator.setDuration(3000); animator.setInterpolator(new AccelerateInterpolator()); animator.start();好了,到这里有关PropertyValuesHolder的ofInt和ofFloat函数的用法就讲完了,大家可以看到PropertyValuesHolder使用起来也很容易,下面我们再来看看PropertyValuesHolder的ofObject的使用方法。
public static PropertyValuesHolder ofObject(String propertyName, TypeEvaluator evaluator,Object... values)
public static ObjectAnimator ofObject(Object target, String propertyName,TypeEvaluator evaluator, Object... values)
这里实现的效果与《Animation动画详解(六)——ValueAnimator高级进阶(二)》实现的效果相同,即通过自字义的CharEvaluator来自动实现字母的改变与计算。
首先是自定义一个CharEvaluator,通过进度值来自动计算出当前的字母:
public class CharEvaluator implements TypeEvaluator<Character> { @Override public Character evaluate(float fraction, Character startValue, Character endValue) { int startInt = (int)startValue; int endInt = (int)endValue; int curInt = (int)(startInt + fraction *(endInt - startInt)); char result = (char)curInt; return result; } }有关数字与字符间转换的原理已经在 《Animation动画详解(六)——ValueAnimator高级进阶(二)》讲述,就不再细讲。这个CharEvaluator也是直接从这篇文章中拿过来的,强烈建议大家对这个系列文章从头开始看。
public class MyTextView extends TextView { public MyTextView(Context context, AttributeSet attrs) { super(context, attrs); } public void setCharText(Character character){ setText(String.valueOf(character)); } }在这里,我们定义了一个方法setCharText(Character character),参数就是Character类型,我们知道这个方法所对应的属性是CharText;
public class MyActivity extends Activity { private Button btn; private TextView mTextView; private MyTextView mMyTv; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mMyTv = (MyTextView)findViewById(R.id.mytv); btn = (Button) findViewById(R.id.btn); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { doOfObjectAnim(); } }); } private void doOfObjectAnim(){ PropertyValuesHolder charHolder = PropertyValuesHolder.ofObject("CharText",new CharEvaluator(),new Character('A'),new Character('Z')); ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(mMyTv, charHolder); animator.setDuration(3000); animator.setInterpolator(new AccelerateInterpolator()); animator.start(); } }这部分代码,很好理解,在点击按钮的时候执行doOfObjectAnim()方法:
PropertyValuesHolder charHolder = PropertyValuesHolder.ofObject("CharText",new CharEvaluator(),new Character('A'),new Character('Z')); ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(mMyTv, charHolder); animator.setDuration(3000); animator.setInterpolator(new AccelerateInterpolator()); animator.start();首先是根据PropertyValuesHolder.ofObject生成一个PropertyValuesHolder实例,注意它的属性就是CharText,所对应的set函数就是setCharText,由于CharEvaluator的中间值是Character类型,所以CharText属性所对应的完整的函数声明为setCharText(Character character);这也就是我们为什么要自定义一个MyTextView原因,就是因为TextView中没有setText(Character character)这样的函数。
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)
public static PropertyValuesHolder ofKeyframe(String propertyName, Keyframe... values)
Keyframe frame0 = Keyframe.ofFloat(0f, 0); Keyframe frame1 = Keyframe.ofFloat(0.1f, -20f); Keyframe frame2 = Keyframe.ofFloat(1, 0); PropertyValuesHolder frameHolder = PropertyValuesHolder.ofKeyframe("rotation",frame0,frame1,frame2); Animator animator = ObjectAnimator.ofPropertyValuesHolder(mImage,frameHolder); animator.setDuration(1000); animator.start();第一步:生成Keyframe对象;
看起来跟开篇的一样,仔细对比一下,还是有不同的,这里只是实现了左右震动,但并没有放大效果。
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <Button android:id="@+id/btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="start anim"/> <ImageView android:id="@+id/img" android:layout_width="150dp" android:layout_height="wrap_content" android:scaleType="fitCenter" android:layout_gravity="center_horizontal" android:src="@drawable/phone"/> </LinearLayout>这段布局代码没什么难度,就不再讲了,下面来看看MyActivity中的处理
public class MyActivity extends Activity { private ImageView mImage; private Button mBtn; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mImage = (ImageView)findViewById(R.id.img); mBtn = (Button)findViewById(R.id.btn); mBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { doOfFloatAnim(); } }); } 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); PropertyValuesHolder frameHolder = PropertyValuesHolder.ofKeyframe("rotation",frame0,frame1,frame2,frame3,frame4,frame5,frame6,frame7,frame8,frame9,frame10); Animator animator = ObjectAnimator.ofPropertyValuesHolder(mImage,frameHolder); animator.setDuration(1000); animator.start(); } }这段代码难度也不大,在点击按钮的时候,执行doOfFloatAnim()函数,关键问题在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);在这些keyframe中,首先指定在开始和结束时,旋转角度为0,即恢复原样:
Keyframe frame0 = Keyframe.ofFloat(0f, 0); Keyframe frame10 = Keyframe.ofFloat(1, 0);然后在过程中,让它左右旋转,比如在进度为0.2时,旋转到左边20度位置:
Keyframe frame1 = Keyframe.ofFloat(0.1f, -20f);然后在进度为0.3时,旋转到右边20度位置:
Keyframe frame3 = Keyframe.ofFloat(0.3f, -20f);其它类似。正是因为来回左右的旋转,所以我们看起来就表现为在震动
PropertyValuesHolder frameHolder = PropertyValuesHolder.ofKeyframe("rotation",frame0,frame1,frame2,frame3,frame4,frame5,frame6,frame7,frame8,frame9,frame10); Animator animator = ObjectAnimator.ofPropertyValuesHolder(mImage,frameHolder); animator.setDuration(1000); animator.start();最后,利用ObjectAnimator.ofPropertyValuesHolder(mImage,frameHolder)生成ObjectAnimator对象,并开始动画。
/** * ofFloat */ public static Keyframe ofFloat(float fraction) public static Keyframe ofFloat(float fraction, float value) /** * ofInt */ public static Keyframe ofInt(float fraction) public static Keyframe ofInt(float fraction, int value)由于ofFloat和ofInt的构造函数都是一样的,我们这里只以ofFloat来例来说。
public static Keyframe ofFloat(float fraction)这个构造函数比较特殊,只有一个参数fraction,表示当前关键帧所在的动画进度位置。那在这个进度时所对应的值要怎么设置呢?
/** * 设置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的中间值计算过程中,就是用的就是回弹插值器;
Keyframe frame0 = Keyframe.ofFloat(0f, 0); Keyframe frame1 = Keyframe.ofFloat(0.5f, 100f); Keyframe frame2 = Keyframe.ofFloat(1); frame2.setValue(0f); PropertyValuesHolder frameHolder = PropertyValuesHolder.ofKeyframe("rotation",frame0,frame1,frame2); Animator animator = ObjectAnimator.ofPropertyValuesHolder(mImage,frameHolder); animator.setDuration(3000); animator.start();在这段代码中,总共就只有三个关键帧,最后一个Keyframe的生成方法是利用:
Keyframe frame2 = Keyframe.ofFloat(1); frame2.setValue(0f);对于Keyframe而言,fraction和value这两个参数是必须有的,所以无论用哪种方式实例化Keyframe都必须保证这两个值必须被初始化。
Keyframe frame0 = Keyframe.ofFloat(0f, 0); Keyframe frame1 = Keyframe.ofFloat(0.5f, 100f); Keyframe frame2 = Keyframe.ofFloat(1); frame2.setValue(0f); frame2.setInterpolator(new BounceInterpolator()); PropertyValuesHolder frameHolder = PropertyValuesHolder.ofKeyframe("rotation",frame0,frame1,frame2); Animator animator = ObjectAnimator.ofPropertyValuesHolder(mImage,frameHolder); animator.setDuration(3000); animator.start();我们给最后一帧frame2添加上回弹插值器(BounceInterpolator),然后看看效果:
从效果图中可以看出,在frame1到frame2的过程中,使用了回弹插值器,所以从这里也可验证我们上面的论述:如果给当前帧添加插值器,那么在上一帧到当前帧的进度值计算过程中会使用这个插值器。
好了,到这里有关ofInt,ofFloat和常用的几个函数的讲解就结束了,下面我们再来看看ofObject的使用方法。
public static Keyframe ofObject(float fraction) public static Keyframe ofObject(float fraction, Object value)同样,如果使用ofObject(float fraction)来构造,也必须使用setValue(Object value)来设置这个关键帧所对应的值。
明显L前的12个字母变化的特别快,后面的14个字母变化的比较慢。
我们使用到的MyTextView,CharEvaluator都与上面的一样,只是动画部分不同,这里只列出动画的代码:
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')); PropertyValuesHolder frameHolder = PropertyValuesHolder.ofKeyframe("CharText",frame0,frame1,frame2); frameHolder.setEvaluator(new CharEvaluator()); ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(mMyTv,frameHolder); animator.setDuration(3000); animator.start();在这个动画中,我们定义了三帧:
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'));frame0表示在进度为0的时候,动画的字符是A;frame1表示在进度在0.1的时候,动画的字符是L;frame2表示在结束的时候,动画的字符是Z;
frameHolder.setEvaluator(new CharEvaluator());凡是使用ofObject来做动画的时候,都必须调用frameHolder.setEvaluator显示设置Evaluator,因为系统根本是无法知道,你动画的中间值Object真正是什么类型的。
Keyframe frame0 = Keyframe.ofFloat(0f, 0); Keyframe frame1 = Keyframe.ofFloat(0.5f, 100f); Keyframe frame2 = Keyframe.ofFloat(1,0); PropertyValuesHolder frameHolder = PropertyValuesHolder.ofKeyframe("rotation", frame0,frame1,frame2); Animator animator = ObjectAnimator.ofPropertyValuesHolder(mImage, frameHolder); animator.setDuration(3000); animator.start();这里有三个帧,在进度为0.5时,电话向右旋转100度,然后再转回来。
Keyframe frame1 = Keyframe.ofFloat(0.5f, 100f); Keyframe frame2 = Keyframe.ofFloat(1,0); PropertyValuesHolder frameHolder = PropertyValuesHolder.ofKeyframe("rotation",frame1,frame2); Animator animator = ObjectAnimator.ofPropertyValuesHolder(mImage, frameHolder); animator.setDuration(3000); animator.start();效果图如下:
可以看到,动画是直接从中间帧frame1开始的,即当没有第0帧时,动画从最近的一个帧开始。
Keyframe frame0 = Keyframe.ofFloat(0f, 0); Keyframe frame1 = Keyframe.ofFloat(0.5f, 100f); PropertyValuesHolder frameHolder = PropertyValuesHolder.ofKeyframe("rotation", frame0,frame1); Animator animator = ObjectAnimator.ofPropertyValuesHolder(mImage, frameHolder); animator.setDuration(3000); animator.start();效果图如下:
PropertyValuesHolder frameHolder = PropertyValuesHolder.ofKeyframe("rotation",frame1); Animator animator = ObjectAnimator.ofPropertyValuesHolder(mImage, frameHolder); animator.setDuration(3000); animator.start();在点击按钮开始动画时,就直接崩了,报错信息如下:
报错问题是数组越界,也就是说,至少要有两个帧才行。
Keyframe frame1 = Keyframe.ofFloat(0.5f, 100f); Keyframe frame2 = Keyframe.ofFloat(0.7f,50f); PropertyValuesHolder frameHolder = PropertyValuesHolder.ofKeyframe("rotation",frame1,frame2); Animator animator = ObjectAnimator.ofPropertyValuesHolder(mImage, frameHolder); animator.setDuration(3000); animator.start();效果图如下:
可以看到,在保留两个帧的情况下,是可以运行的,而且,由于去掉了第0帧,所以将frame1做为起始帧,又由于去掉了结束帧,所以将frame2做为结束帧。
下面我们做出结论:
发现了没,除了左右震动,图标在震动过程中始终是放大的。
上面,我们已经实现了左右震动,下面我们再添加放大效果就好了。
框架的部分就不再讲了,与上面一样,只是动画部分不同,先贴出动画的完整代码:
/** * 左右震动效果 */ 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); PropertyValuesHolder frameHolder1 = PropertyValuesHolder.ofKeyframe("rotation", frame0, frame1, frame2, frame3, frame4,frame5, frame6, frame7, frame8, frame9, frame10); /** * scaleX放大1.1倍 */ Keyframe scaleXframe0 = Keyframe.ofFloat(0f, 1); Keyframe scaleXframe1 = Keyframe.ofFloat(0.1f, 1.1f); Keyframe scaleXframe2 = Keyframe.ofFloat(0.2f, 1.1f); Keyframe scaleXframe3 = Keyframe.ofFloat(0.3f, 1.1f); Keyframe scaleXframe4 = Keyframe.ofFloat(0.4f, 1.1f); Keyframe scaleXframe5 = Keyframe.ofFloat(0.5f, 1.1f); Keyframe scaleXframe6 = Keyframe.ofFloat(0.6f, 1.1f); Keyframe scaleXframe7 = Keyframe.ofFloat(0.7f, 1.1f); Keyframe scaleXframe8 = Keyframe.ofFloat(0.8f, 1.1f); Keyframe scaleXframe9 = Keyframe.ofFloat(0.9f, 1.1f); Keyframe scaleXframe10 = Keyframe.ofFloat(1, 1); PropertyValuesHolder frameHolder2 = PropertyValuesHolder.ofKeyframe("ScaleX",scaleXframe0,scaleXframe1,scaleXframe2,scaleXframe3,scaleXframe4,scaleXframe5,scaleXframe6,scaleXframe7,scaleXframe8,scaleXframe9,scaleXframe10); /** * scaleY放大1.1倍 */ Keyframe scaleYframe0 = Keyframe.ofFloat(0f, 1); Keyframe scaleYframe1 = Keyframe.ofFloat(0.1f, 1.1f); Keyframe scaleYframe2 = Keyframe.ofFloat(0.2f, 1.1f); Keyframe scaleYframe3 = Keyframe.ofFloat(0.3f, 1.1f); Keyframe scaleYframe4 = Keyframe.ofFloat(0.4f, 1.1f); Keyframe scaleYframe5 = Keyframe.ofFloat(0.5f, 1.1f); Keyframe scaleYframe6 = Keyframe.ofFloat(0.6f, 1.1f); Keyframe scaleYframe7 = Keyframe.ofFloat(0.7f, 1.1f); Keyframe scaleYframe8 = Keyframe.ofFloat(0.8f, 1.1f); Keyframe scaleYframe9 = Keyframe.ofFloat(0.9f, 1.1f); Keyframe scaleYframe10 = Keyframe.ofFloat(1, 1); PropertyValuesHolder frameHolder3 = PropertyValuesHolder.ofKeyframe("ScaleY",scaleYframe0,scaleYframe1,scaleYframe2,scaleYframe3,scaleYframe4,scaleYframe5,scaleYframe6,scaleYframe7,scaleYframe8,scaleYframe9,scaleYframe10); /** * 构建动画 */ Animator animator = ObjectAnimator.ofPropertyValuesHolder(mImage, frameHolder1,frameHolder2,frameHolder3); animator.setDuration(1000); animator.start();这里的总共分为四步:
Keyframe scaleXframe0 = Keyframe.ofFloat(0f, 1); Keyframe scaleXframe1 = Keyframe.ofFloat(0.1f, 1.1f); Keyframe scaleXframe2 = Keyframe.ofFloat(0.2f, 1.1f); Keyframe scaleXframe3 = Keyframe.ofFloat(0.3f, 1.1f); Keyframe scaleXframe4 = Keyframe.ofFloat(0.4f, 1.1f); Keyframe scaleXframe5 = Keyframe.ofFloat(0.5f, 1.1f); Keyframe scaleXframe6 = Keyframe.ofFloat(0.6f, 1.1f); Keyframe scaleXframe7 = Keyframe.ofFloat(0.7f, 1.1f); Keyframe scaleXframe8 = Keyframe.ofFloat(0.8f, 1.1f); Keyframe scaleXframe9 = Keyframe.ofFloat(0.9f, 1.1f); Keyframe scaleXframe10 = Keyframe.ofFloat(1, 1);非常注意的是,在动画过程中放大1.1倍,在开始动画和动画结束时,都要还原状态,即原大小的1倍值:
Keyframe scaleXframe0 = Keyframe.ofFloat(0f, 1); Keyframe scaleXframe10 = Keyframe.ofFloat(1, 1);第三步,同样利用View类的SetScaleY(float value)方法,在动画过程中将图片纵向放大1.1倍。原理与scaleX相同,就不再细讲。
Animator animator = ObjectAnimator.ofPropertyValuesHolder(mImage, frameHolder1,frameHolder2,frameHolder3);我们前面讲过,ObjectAnimator ofPropertyValuesHolder(Object target,PropertyValuesHolder… values)中第二个参数是可变长参数,可以传进去任何多个PropertyValuesHolder对象,这些对象所对应的动画会同时作用于控件上。这里我们就将三个属性动画同时作用在mImage上,所以图片的动画就表现为在左右震动的同时,横向放大1.1倍,纵向也放大了1.1倍。
/** * 设置动画的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)这些函数都比较好理解,setFloatValues(float… values)对应PropertyValuesHolder.ofFloat(),用于动态设置动画中的数值。setIntValues、setKeyframes、setObjectValues同理;
/** * 设置动画的Evaluator */ public void setEvaluator(TypeEvaluator evaluator)如果是利用PropertyValuesHolder.ofObject()来创建动画实例的话,我们是一定要显示调用 PropertyValuesHolder.setEvaluator()来设置Evaluator的。在上面的字母转换的例子中,我们已经用过这个函数了。这里也就没什么好讲的了。
源码内容:
1、《BlogPropertyValuesHolder》:第一部分PropertyValuesHolder所对应源码
2、《BlogKeyframe》:第三部分Keyframe所对应源码
如果本文有帮到你,记得加关注哦
源码下载地址:
CSDN:http://download.csdn.net/detail/harvic880925/9445780
github:https://github.com/harvic/BlogResForGitHub
请大家尊重原创者版权,转载请标明出处:http://blog.csdn.net/harvic880925/article/details/50752838 谢谢