1、概述
对于之前介绍的Animation,它属于视图动画(View Animation)(可参见:Animation 动画详解),包括补间动画(Tween Animation)和逐帧动画(Tween Animation);而在android中还有另一种动画,那就是属性动画(Property Animator),它包括ValueAnimator 和 ObjectAnimator。
两者的区别:
- 引入时间不同
视图动画在API Level 1 引入的,而属性动画在API Level 11(即 android 3.0)引入的;
- 所在包不同
视图动画在 android.view.animation.Animation包下,属性动画在:android.animation包下
- 动画类的命名不同
视图动画中类的名字为:XXXAnimation,而在属性动画中是:XXXAnimator
- 作用的对象不同(这个也是引入属性动画的原因)
视图动画是对控件做动画,不能改变控件内部的属性,对所有的控件都可以;而属性动画是通过改变控件的属性来实现动画,但使用ObjectAnimator时要求作用的控件的属性要有get,set方法。如果控件的属性没有get/set方法,可以通过包装类间接的设置get/set方法,或者使用ValueAnimator 实现。
2、ValueAnimator 的基本使用
ValueAnimator是动画的核心,但不提供任何动画效果,它更像一个数值发生器,产生具有一定规律的数字,然后让调用者来控制动画的实现过程。用法如下:
- 创建ValueAnimator实例
例:创建0到500的动画,时间为1s:1 2
| ValueAnimator animator = ValueAnimator.ofInt(0,500); animator.setDuration(1000);
|
代码中可以看出,它不与任何控件关联,只对动画做运算。
添加它的监听事件
下面是给它添加监听事件,实现动画的。
1 2 3 4 5 6 7 8 9
| animator.addUpdateListener(new ValueAnimator. AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { //具体处理动画逻辑 } }); //开启动画 animator.start();
|
具体示例:
点击按钮使textView从(200,200)移动到(600,,600)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| btnStartAnim = (Button) findViewById(R.id.btn); tv = (TextView) findViewById(R.id.tv); btnStartAnim.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //设置数据 ValueAnimator animator = ValueAnimator.ofInt(200, 600); animator.setDuration(1000); //监听动画 animator.addUpdateListener(new ValueAnimator. AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { //获取当前动画的值 int curValue = (int) animation.getAnimatedValue(); //设置tv的位置 tv.layout(curValue, curValue, curValue + tv.getWidth(), curValue + tv.getHeight()); } }); //开启动画 animator.start(); } });
|
示例效果:
3、ValueAnimator 常用方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| /** * 设置动画参数,参数类型为可变参数 */ ValueAnimator ofInt(int... values); ValueAnimator ofFloat(int... values); /** * 设置动画时长,单位是毫秒 */ ValueAnimator setDuration(long duration); /** * 获取 ValueAnimator 在运动时,当前运动点的值 */ Object getAnimatedValue(); /** * 开始动画 */ void start(); /** * 设置循环次数,设置为 INFINITE 表示无限循环 */ void setRepeatCount(int value); /** * 设置循环模式 * value 取值有 RESTART,REVERSE(分别为:重新开始,倒序重新开始) */ void setRepeatMode(int value); /** * 取消动画 */ void cancel();
|
通过源码,发现ofInt和ofFloat方法内部实现一样的,他们的区别在于传入的参数类型不同,需要注意的是在使用getAnimatedValue方法时,如果前面使用的是ofInt,要强转成int 类型,否则,转为float类型。
此外,如果不需要动画,可以调用移除动画监听方法,但需要先调用cancel方法取消动画。
4、ObjectAnimator 的基本使用
ObjectAnimator 类继承自ValueAnimator,使用时通过静态工厂类直接返回一个对象,参数包括对象和对象的属性名,但该属性必须要有get和set函数,这样可以真实的控制一个view的属性值,因此它基本可以实现所有的动画效果。
使用示例:
使textView的translationX从0变化到200在变化到500,持续时间为1s,代码如下:
1 2 3 4
| ObjectAnimator animator = ObjectAnimator.ofFloat(textView, "translationX",new float[]{200,500}); animator.setDuration(1000); animator.start();
|
ofFloat的参数:第一个是要操纵的View;第二个是要操纵的属性;第三个是参数,是一个可变数组。同样的,可以给它设置显示时长,插值器等。
在开始提到了,ObjectAnimator用于有get,set属性的控件,对于没有的可以通过一个包装类来实现,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| /** * 包装类,给width添加get,set方法 */ public static class WrapperView { private View mTarget; public WrapperView(View target) { mTarget = target; } public int getWidth() { return mTarget.getLayoutParams().width; } public void setWidth(int width) { mTarget.getLayoutParams().width = width; mTarget.requestLayout(); } }
|
使用时,直接操纵包装类,如下:
1 2 3 4
| WrapperView mWrapperView = new WrapperView(btnStartAnim); ObjectAnimator animator = ObjectAnimator.ofInt( mWrapperView,"width",500).setDuration(500); animator.start();
|
通过上面,可以知道,ObjectAnimator 实现动画主要是通过set方法来设置控件的对应的属性实现动画。
5、ObjectAnimator 的常用方法
除了上面的ofInt,ofFloat方法,对于要改变背景色的,可以使用ArgbEvaluator,用法如下,给textView设置背景色在三种颜色间变化:
1 2 3 4 5
| ObjectAnimator animator = ObjectAnimator.ofInt(textView, "BackgroundColor",0xffff00ff, 0xffffff00, 0xffff00ff); animator.setDuration(2000); animator.setEvaluator(new ArgbEvaluator()); animator.start();
|
其他常用函数如下:
摘抄于:http://wiki.jikexueyuan.com/project/android-animation/7.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| /** * 设置动画时长,单位是毫秒 */ ValueAnimator setDuration(long duration) /** * 获取 ValueAnimator 在运动时,当前运动点的值 */ Object getAnimatedValue(); /** * 开始动画 */ void start() /** * 设置循环次数,设置为 INFINITE 表示无限循环 */ void setRepeatCount(int value) /** * 设置循环模式 * value 取值有 RESTART,REVERSE, */ void setRepeatMode(int value) /** * 取消动画 */ void cancel()
|
监听相关的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| /** * 监听器一:监听动画变化时的实时值 */ public static interface AnimatorUpdateListener { void onAnimationUpdate(ValueAnimator animation); } //添加方法为:public void addUpdateListener(AnimatorUpdateListener listener) /** * 监听器二:监听动画变化时四个状态 */ public static interface AnimatorListener { void onAnimationStart(Animator animation); void onAnimationEnd(Animator animation); void onAnimationCancel(Animator animation); void onAnimationRepeat(Animator animation); } //添加方法为:public void addListener(AnimatorListener listener)
|
插值器与 Evaluator:
1 2 3 4 5 6 7 8
| /** * 设置插值器 */ public void setInterpolator(TimeInterpolator value) /** * 设置 Evaluator */ public void setEvaluator(TypeEvaluator value)
|
更多方法可以查看api
6、AnimatorSet的使用
在视图动画中 AnimationSet 来处理混合动画,同样的,这里的AnimatorSet来处理多个动画的。它出了实现多种动画,还可以精确的进行顺序控制。
示例代码:
1 2 3 4 5 6 7
| ObjectAnimator animator1 = ObjectAnimator.ofFloat(textView, "translationX", 300); ObjectAnimator animator2 = ObjectAnimator.ofFloat(textView, "scaleX", 1, 0, 1); ObjectAnimator animator3 = ObjectAnimator.ofFloat(textView, "scaleY", 1, 0, 1); AnimatorSet animatorSet = new AnimatorSet(); animatorSet.setDuration(1000); animatorSet.playTogether(animator1, animator2, animator3); animatorSet.start();
|
示例效果:
以上示例设置textView在x轴方向移动300,x和y方向先缩小到一倍再还原到一倍三种动画是同时执行。
若需要按顺序执行,可以调用Animator的playSequentially方法。
7、PropertyValuesHolder 的使用
除了上面讲的AnimatorSet 实现多种动画,还可以通过PropertyValuesHolder来实现,比如上面的例子在平移的过程中实现x,y轴的缩放。如下代码;
1 2 3 4 5 6 7 8
| PropertyValuesHolder valuesHolder1 = PropertyValuesHolder .ofFloat("translationX", 300); PropertyValuesHolder valuesHolder2 = PropertyValuesHolder .ofFloat("scaleX", 1, 0, 1); PropertyValuesHolder valuesHolder3 = PropertyValuesHolder .ofFloat("scaleY", 1, 0, 1); ObjectAnimator.ofPropertyValuesHolder(tv, valuesHolder1, valuesHolder2, valuesHolder3).setDuration(1000).start();
|
运行效果同AnimatorSet中的示例。
它的实现是先分别用PropertyValuesHolder的对象来控制不同的属性,最后调用ofPropertyValuesHolder方法实现多个属性动画的共同作用。
8、在XML文件中实现属性动画
先在xml文件中定义属性,如下示例:
1 2 3 4 5 6 7 8
| <?xml version="1.0" encoding="utf-8"?> <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"> android:duration=1000" android:propertyName="scaleX" android:valueFrom="1.0" android:valueTo="2.0" android:valueType="floatType" </objectAnimator>
|
在java代码代码中使用:
1 2 3 4 5
| Animator animator = AnimatorInflater. loadAnimator(MainActivity.this, R.animator.scalex); animator.setTarget(tv); animator.start();
|
需要注意的是,xml文件的定义需要放在res/animator下,而且根节点只能是:set,objectAnimator,valueAnimator三者之一。如果使用的set,可以为其指定播放的方式,属性名为:ordering=[“together”]|[“sequentially”],
默认值为:“together”,对于其他具体的属性这里不再赘述了,可以参见文档。
在实际开发中建议使用代码实现动画,比较简单,而且很多时候某些属性的起始值无法确定。
8、View的animate方法
在android3.0之后,添加了animate方法来直接驱动属性动画,它其实是对属性动画的简写,如下示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| view.animate() .alpha(0) .y(300) .setDuration(1000) .withStartAction(new Runnable() { @Override public void run() { } }) .withEndAction(new Runnable() { @Override public void run() { } }).start();
|
上面的例子很好理解,可以通过属性来确定他的含义。
总之,在实现动画时,可以根据自己的实际情况选择相应的方式实现动画,必要的时候还可以自定义实现动画,往往在使用时,不只是一种动画,我们要选择合适的方式实现多种动画。
上一篇:TabLayout+ViewPager创建tab
下一篇:Animation 动画详解