Android动画主要分为三大类:View Animation Drawable Animation Property Animation
- Drawable Animations对大多数人来说是三者中最容易理解的,其实它就是很多书籍中提到的逐帧动画。而Property Animation和View Animation是相对比较容易混淆的,下面先讲解二者的区别。
- View Animation有两个缺点:(1)View Animation一般只能修改组件(View Object)的部分属性,比如:scaling(大小)和rotation(旋转),但是无法修改组件的背景颜色。(2)View Animation使某个组件产生动画效果移动一段距离后,比如从屏幕左侧移动到右侧,其实整个过程是绘制出来的效果,该组件真正的位置依然保留在左侧,只有点击左侧位置才能触发该组件。所以想真正移动某组件,需要在动画结束后添加代码实现。
- Property Animation则没有以上View Animation的两个限制,Property Animation可以修改任何对象(View Object 或者 non-view Object)的任何属性,比如大小,旋转,颜色。并且,移动后的组件,位置也回跟随着改变。
Android官网推荐使用Property Animation,但是View Animation也有其优点:使用方便简单,所以当View Animation能方便快速地解决需求时,选择它也是不错的选择。
1. View/Tweened Animations(过渡动画):该类Animations提供了旋转、移动、伸展和淡出等效果。
Alpha——淡入淡出,Scale——缩放效果,Rotate——旋转,Translate——移动效果。
AnimationSet set = new AnimationSet(false); // 第一步, 创建AnmiationSet对象 Animation animation = new AlphaAnimation(0,1); // 控制渐变透明的动画效果 第二步,动画类型 animation.setDuration(500); // 动画时间毫秒数 第三步,动画执行时间 set.addAnimation(animation); // 第四步,加入动画集合 animation = new TranslateAnimation(1, 13, 10, 50); // ScaleAnimation 控制尺寸伸缩的动画效果 animation.setDuration(300); set.addAnimation(animation); animation = new RotateAnimation(30,10); // TranslateAnimation 控制画面平移的动画效果 animation.setDuration(300); set.addAnimation(animation); animation = new ScaleAnimation(5,0,2,0); // RotateAnimation 控制画面角度变化的动画效果 animation.setDuration(300); set.addAnimation(animation); LayoutAnimationController controller = new LayoutAnimationController(set, 1); GridView gridView = (GridView) this.findViewById(R.id.gridview); gridView .setLayoutAnimation(controller); // GridView 设置动画效果 第五步,设置给view ListView listview= (ListView)this.findViewById(R.id.listview); // 也可以View.startAnimation()开始执行 listview.setLayoutAnimation(controller); // ListView 设置动画效果
2. Drawable/Frame-by-frame Animations(帧动画):
这一类Animations可以创建一个Drawable序列,这些Drawable可以按照指定的时间间歇一个一个的显示,类似电影。使用方法:
1)在drawable/anim目录下新建一个frame.xml文件
<?xml version="1.0" encoding="utf-8"?> <animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false"> // oneshot 为true的话,此动画只会执行一次,如果为false则一直循环。 <item android:drawable="@drawable/f1" android:duration="300" /> <item android:drawable="@drawable/f2" android:duration="300" /> <item android:drawable="@drawable/f3" android:duration="300" /> <item android:drawable="@drawable/f4" android:duration="300" /> </animation-list>
我们可以将frame.xml文件放置于drawable或anim目录,官方文档上是放到了drawable中了,大家可以根据喜好来放置,放在这两个目录都是可以运行的。
2)执行动画命令:
image.setBackgroundResource(R.anim.frame); AnimationDrawable anim = (AnimationDrawable) image.getBackground(); anim.start();
3. Property Animations(属性动画):
Property Animation 是Android3.0(level 11)引入的一个款功能强大、灵活、健壮的动画系统,它可以为任何包括View在内的对象添加动画效果。就实现原理来分析,Property Aniamtion和Tween Animation之间最大的区别就是前者在为对象添加动画效果时,其更改的是对象的实际属性,而后者改变的只是View的绘制效果,View的实际属性值是不发生改变的。会用到的监听器和接口如下
Animator.AnimatorListener:
onAnimationStart() —— 动画开始时调用; onAnimationEnd() —— 动画结束时调用;
onAnimationRepeat() —— 动画循环播放时调用; onAnimationCancel() —— 动画被取消时调用。
Animator.AnimatorUpdateListener:
onAnimationUpdate() —— 动画每播放一帧时调用。
在动画过程中,可侦听此事件来获取并使用 ValueAnimator 计算出来的属性值。利用传入事件的 ValueAnimator 对象,调用其 getAnimatedValue() 方法即可获取当前的属性值。如果使用 ValueAnimator来实现动画的话 ,则必需实现此侦听器。
使用ValueAnimator实现动画的步骤及实践:
1. 调用ValueAnimation类中的ofInt(int...values)、ofFloat(String propertyName,float...values)等静态方法实例化ValueAnimator对象,并设置目标属性的属性名、初始值或结束值等值;
2. 调用addUpdateListener(AnimatorUpdateListener mListener)方法为ValueAnimator对象设置属性变化的监听器;
3. 调用setInterpolator(TimeInterpolator value)为ValueAniamtor设置自定义的Interpolator(插值器,定义了动画变化过程中的属性变化规则); (可选)
4. 调用setEvaluator(TypeEvaluator value)为ValueAnimator设置自定义的TypeEvaluator(估值器,告诉动画系统如何从初始值过度到结束值); (可选)
5. 在AnimatorUpdateListener 中的实现方法为目标对象的属性设置计算好的属性值。
6. 设置动画的持续时间、是否重复及重复次数等属性;
7. 为ValueAnimator设置目标对象并开始执行动画。
/** 使用ValueAnimator实现图片缩放动画 */ public void scaleValueAnimator(){ //1.设置目标属性名及属性变化的初始值和结束值 PropertyValuesHolder mPropertyValuesHolderScaleX = PropertyValuesHolder.ofFloat("scaleX", 1.0f,0.0f); PropertyValuesHolder mPropertyValuesHolderScaleY = PropertyValuesHolder.ofFloat("scaleY", 1.0f,0.0f); ValueAnimator mAnimator = ValueAnimator.ofPropertyValuesHolder(mPropertyValuesHolderScaleX,mPropertyValuesHolderScaleY); //2.为目标对象的属性变化设置监听器 mAnimator.addUpdateListener(new AnimatorUpdateListener() { public void onAnimationUpdate(ValueAnimator animation) { // 3.根据属性名获取属性变化的值分别为ImageView目标对象设置X和Y轴的缩放值 float animatorValueScaleX = (float) animation.getAnimatedValue("scaleX"); float animatorValueScaleY = (float) animation.getAnimatedValue("scaleY"); mImageViewTest.setScaleX(animatorValueScaleX); mImageViewTest.setScaleY(animatorValueScaleY); } }); //4.为ValueAnimator设置自定义的Interpolator mAnimator.setInterpolator(new CustomInterpolator()); //5.设置动画的持续时间、是否重复及重复次数等属性 mAnimator.setDuration(2000); mAnimator.setRepeatCount(3); mAnimator.setRepeatMode(ValueAnimator.REVERSE); //6.为ValueAnimator设置目标对象并开始执行动画 mAnimator.setTarget(mImageViewTest); mAnimator.start(); }
上面代码列表中,我们通过PropertyValuesHolder类为目标属性名来设置属性值的初始值和结束值,然后ValueAnimator通过调用ofPropertyValuesHolder(PropertyValuesHolder...values)设置已经配置好的PropertyValuesHolder对象。不过需要注意的是使用PropertyValuesHolder设置的属性必须是目标对象的属性中有setXX()方法才能进行设置,例如ImageView对象中有setScaleX()方法才能为ImageView设置对应属性的PropertyValuesHolder对象。接着ValueAnimator对象调用setInterpolator(TimeInterpolator value)设置自定义的Interpolator,类名为CustomInterpolator,具体的代码如下:
public class CustomInterpolator implements TimeInterpolator { public float getInterpolation(float input) { input *= 0.8f; return input * input; } }
接着,为ValueAnimator对象设置相应的属性,如动画重复次数、动画所持续的时间等等。最后,为ValueAnimator设置目标对象并启动动画。
另外还有一个,ObjectAnimator类,作为ValueAnimator的子类,不仅继承了它的所有方法和特性,并且还封装很多实用的方法,方便开发人员快速实现动画。同时,由于属性值会自动更新,使用ObjectAnimator实现动画不需要像ValueAnimator那样必须实现 ValueAnimator.AnimatorUpdateListener ,因此实现任意对象的动画显示就更加容易了。我们在大部分的开发工作中,都会使用ObjectAnimator而非ValueAnimator实现我们所需的动画效果。
ObjectAnimator实现动画的几个步骤,如下:
首先,通过调用ofFloat()、ofInt()等方法创建ObjectAnimator对象,并设置目标对象、需要改变的目标属性名、初始值和结束值;然后,设置动画的持续时间、是否重复及重复次数等属性;最后,启动动画,就完成了。
使用ObjectAnimator实现动画也有一些要求和限制,一般有以下几点需要注意:
1.动画显示的属性必须带有一个 setter 方法,因为 ObjectAnimator 会在动画期间自动更新属性值,它必须能够用此 setter 方法访问到该属性。 例如:假设属性名称为foo,则需要有一个setFoo()方法。 而你如果此 setter 方法不存在,那么我们可以有以下三种选择:<1>如果权限允许的话,直接在类中增加此 setter 方法;<2>修改封装类来增加此 setter 方法,并让该封装类来接收属性值并传给初始的对象;<3>换用 ValueAnimator。
2.如果在调用 ObjectAnimator 的某个工厂方法时,我们只为 values... 参数指定了一个值,那此值将被认定为动画属性的结束值。 这样的话,动画显示的属性必须带有一个 getter 方法,用于获取动画的起始值。 此 getter 方法必须以get<propertyName>()的格式命名。 例如:假设属性名为foo,则需要有一个getFoo()方法。
3.动画属性的 getter 方法和 setter 方法所操作数据的类型必须与 ObjectAnimator 中设定的起始和结束值相同