android开发中用到的动画实现方式有三种,即View动画、Drawable动画以及属性动画三种动画的实现方式,关于这些动画的实现方式网上很多文章都总结的很详细了,写这篇文章完全是为了自己总结记录,而且本文不会去追究代码细节的问题,就单单总结下怎么用的问题,具体代码细节的话,请参考本文的参考文献。

1、View动画

View动画的实现是通过View控件的setAnimation来设置动画,可以设置的动画有限,只有以下四种

  • AlphaAnimation: 透明度动画
  • RotateAnimation: 旋转动画
  • ScaleAnimation: 缩放动画
  • TranslateAnimation: 平移动画

四种动画的作用看名字应该就清楚了,这里以RotateAnimation为例来说说使用View动画的两种方式

第一种是通过xml的方式来实现(三种动画实现方式都可以通过xml配置的方式来实现),在res/anim目录下创建一个view_animation_rotate.xml 内容如下

<!--   
  * android:fromDegrees="-50":动画开始执行时的控件起始状态的角度;  
  * android:toDegrees="360":动画结束执行时的控件结束状态的角度;  
  * android:pivotX="50%":旋转动画的中心点的X轴方向的横坐标,Value正值(例如50%)时,意思是相对于控件的原始位置往右方向的50%控件宽度的位置为横坐标,  
  *                         若Value为负值(例如-50%),则表示往左方向;当Value为数值时,则代表相对于屏幕的(px)像素值;  
  * android:pivotY="50%":旋转动画的中心店的Y轴方向的纵坐标,原理同上;  
  * android:startOffset="1000":动画执行前的延迟时间;  
  * android:fillAfter="true":当Value为true,表示动画执行结束后停留在结束后的状态;  
  * android:duration="2500":设置每一次动画持续的时间值,单位为毫秒(ms);  
  * android:repeatCount="5":设置动画重复的次数;  
  * android:repeatMode="reverse":设置动画重复的模式:  
  *     reverse为0.0 -> 1.0 -> 0.0,动画反复执行;  
  *     restart为0.0 -> 1.0, 0.0 -> 1.0,动画每次都重新开始执行  
-->  

<rotate xmlns:android="http://schemas.android.com/apk/res/android"  
   android:interpolator="@android:anim/accelerate_decelerate_interpolator"  
   android:fromDegrees="520"  
   android:toDegrees="3600"  
   android:pivotX="50%"  
   android:pivotY="50%"  
   android:startOffset="1000"  
   android:fillAfter="true"  
   android:duration="2500"  
   android:repeatCount="4"  
   android:repeatMode="reverse"  
/>

定义好xml后,便可通过AnimationUtils类来加载xml生成一个动画对象,注意这个AnimationUtils类不是我们自己定义的类,而是Android Sdk提供的android.view.animation包中的类。

/** 
* xml文件加载图片旋转(Rotate)动画 
*/  
RotateAnimation mAnimation = AnimationUtils.loadAnimation(this, R.anim.view_animation_rotate);

这里生成了一个RotateAnimation的对象,调用view.setAnimation(mAnimation)便设置好了view控件的动画。

当然另外一种实现ViewAnimation的方法就是直接通过new RotateAnimation的方式实现,并且在新建的时候传入基本动画参数。

/** 
* 代码创建图片旋转(Rotate)动画 
* mAnimation = new RotateAnimation(fromDegrees, toDegrees, pivotXType, pivotXValue, pivotYType, pivotYValue); 
* fromDegrees:动画开始执行时的控件起始状态的角度; 
* toDegrees:动画结束执行时的控件结束状态的角度; 
* pivotXType:动画在X轴相对于物件位置类型 ,分为RELATIVE_TO_SELF、RELATIVE_TO_PARENT和ABSOLUTE三种类型: 
*                       1、RELATIVE_TO_SELF:相对于控件自身; 
*                       2、RELATIVE_TO_PARENT:相对于父控件; 
*                       3、ABSOLUTE:绝对坐标; 
* pivotXValue:动画开始执行时X轴方向的的起始位置,当位置类型为RELATIVE_TO_SELF时,Value取0.0f~1.0f之间,当位置类型为RELATIVE_TO_PARENT或ABSOLUTE时,Value使用(px)像素值; 
* pivotYType:动画在Y轴相对于物件位置类型 ,分为RELATIVE_TO_SELF、RELATIVE_TO_PARENT和ABSOLUTE三种类型; 
* pivotYValue:旋转动画的中心点的Y轴方向的纵坐标,原理同上; 
*/  
//mAnimation = new RotateAnimation(fromDegrees, toDegrees)  
//mAnimation = new RotateAnimation(fromDegrees, toDegrees, pivotX, pivotY)  
RotateAnimation mAnimation = new RotateAnimation(-50f, 360f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
mAnimation.setDuration(2000);

到这类两种实现View动画的方式就说清楚了,当然我们可能有将四种View动画方式结合起来使用,这个需求也好办,可通过AnimationSet这个动画集合类来实现,也可以在通过在res/anim目录下的xml文件中配置多个动画的方式来实现,这里就不展开说明了。

2、Drawable动画

Drawable动画名称来自于实现Drawable动画的xml文件时放在res/drawable目录中的,比如我们要实现一个机器人走动的动画,那么便可在drawable中放置机器人走动的图片

android spring动画 android实现动画_xml

然后在res/drawable下创建drawable_animation_robot.xml文件,内容如下

<animation-list xmlns:android="http://schemas.android.com/apk/res/android"  
    android:oneshot="false">  
    <item android:drawable="@drawable/drawable_animation01" android:duration="80"/>  
    <item android:drawable="@drawable/drawable_animation02" android:duration="80"/>  
    <item android:drawable="@drawable/drawable_animation03" android:duration="80"/>  
    <item android:drawable="@drawable/drawable_animation04" android:duration="80"/>  
    <item android:drawable="@drawable/drawable_animation05" android:duration="80"/>  
    <item android:drawable="@drawable/drawable_animation06" android:duration="80"/>  
    <item android:drawable="@drawable/drawable_animation07" android:duration="80"/>  
    <item android:drawable="@drawable/drawable_animation08" android:duration="80"/>  
    <item android:drawable="@drawable/drawable_animation09" android:duration="80"/>  
    <item android:drawable="@drawable/drawable_animation10" android:duration="80"/>  
    <item android:drawable="@drawable/drawable_animation11" android:duration="80"/>  
    <item android:drawable="@drawable/drawable_animation12" android:duration="80"/>  
    <item android:drawable="@drawable/drawable_animation13" android:duration="80"/>  
    <item android:drawable="@drawable/drawable_animation14" android:duration="80"/>  
    <item android:drawable="@drawable/drawable_animation15" android:duration="80"/>  
    <item android:drawable="@drawable/drawable_animation16" android:duration="80"/>  
</animation-list>

设置好xml后,便可通过下面代码去获得Drawable动画

//设置背景  
view.setBackgroundResource(R.drawable.drawable_animation_robot);  

//获取当前的背景  
mAnimationDrawable = (AnimationDrawable) view.getBackground();

通过以下代码便可以开启动画或者关闭动画

//开启动画
mAnimationDrawable.start();

//关闭动画
mAnmationDrawable.stop();

到这类Drawable动画就算是说清楚了。

3、属性动画

属性动画是三种动画实现里最复杂的也是最灵活的,它通过去设置控件的属性从而实现动画效果,与属性动画相关且的有以下一些类

  • ObjectAnimator: 动画执行类
  • ValueAnimator: 动画执行类
  • AnimatorSet: 用于控制一组动画的执行
  • AnimatorInflater : 用户加载属性动画xml文件
  • TypeEvaluator: 类型估值器
  • TimeInteplotor:时间插值器

上面的这些类在实现属性动画时会被经常用到,下面来进行分别讲解。

3.1 ObjectAnimator 、 ValueAnimator 、 AnimatorSet这几个类的使用

从以上类中可以看出动画执行类主要有两个,分别是ObjectAnimator和ValueAnimator,其主要区别在于ObjectAnimator在实现动画的时候需要首先指定动画属性,而ValueAnimator则不需要,ValueAnimator是在addUpdateListener中通过set方法去指定属性。

ObjectAnimator实现动画

ObjectAnimator  
.ofFloat(view, "rotationY", 0.0F, 360.0F)//指定了属性rotationY
.setDuration(500)
.start();

ValueAnimator实现动画

ValueAnimator animator = ValueAnimator.ofFloat(0, mScreenHeight - mBlueBall.getHeight());  
animator.setTarget(mBlueBall);  
animator.setDuration(1000).start();  
animator.addUpdateListener(new AnimatorUpdateListener()  
{  
    @Override  
    public void onAnimationUpdate(ValueAnimator animation)  
    {   
        //在addUpdateListener中通过set方法指定属性
        mBlueBall.setTranslationY((Float) animation.getAnimatedValue());  
    }  
});

这里我们看到无论是使用ObjectAnimator还是ValueAnimator这里都是对一个属性进行的动画操作,那么如果要同时操作几个属性动画呢?当然我们可以使用AnimatorSet类去实现,但是如果我们不使用AnimatorSet类呢?

针对ObjectAnimator可以使用addUpdateListener的方式实现

ObjectAnimator anim = ObjectAnimator
        .ofFloat(view, "zhy", 1.0F,  0.0F)
        .setDuration(500);
anim.start();  
anim.addUpdateListener(new AnimatorUpdateListener()  
{  
    @Override  
    public void onAnimationUpdate(ValueAnimator animation)  
    {  
        float cVal = (Float) animation.getAnimatedValue();  
        view.setAlpha(cVal);  
        view.setScaleX(cVal);  
        view.setScaleY(cVal);  
    }  
});

这里的缺点很明显,就是三个属性,我们设置的变化参数却只有一个,于是针对ObjectAnimator我们可以使用PropertyValuesHolder类来完成多属性动画操作,来解决这个问题

PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("alpha", 1f, 0f, 1f);  
PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("scaleX", 1f, 0, 1f);  
PropertyValuesHolder pvhZ = PropertyValuesHolder.ofFloat("scaleY", 1f, 0, 1f);  
ObjectAnimator.ofPropertyValuesHolder(view, pvhX, pvhY,pvhZ).setDuration(1000).start();

这里针对多属性,便可以有有多个变化参数去设置动画效果。

ValueAnimator实现多属性动画操作同样的可以使用addUpdateListener以及PropertyValuesHolder两种方法。

当然实现多属性动画操作,还可以使用AniamtorSet这个类来实现

AnimatorSet实现动画集合

使用AnimatorSet这个类可以规定动画的执行先后顺序,各自的执行时间等,使用起来特别灵活

float cx = mBlueBall.getX();  
ObjectAnimator anim1 = ObjectAnimator.ofFloat(mBlueBall, "scaleX", 1.0f, 2f);  
ObjectAnimator anim2 = ObjectAnimator.ofFloat(mBlueBall, "scaleY", 1.0f, 2f);  
ObjectAnimator anim3 = ObjectAnimator.ofFloat(mBlueBall, "x",  cx ,  0f);  
ObjectAnimator anim4 = ObjectAnimator.ofFloat(mBlueBall, "x", cx);  

/** 
 * anim1,anim2,anim3同时执行 
 * anim4接着执行 
 */  
AnimatorSet animSet = new AnimatorSet();  
animSet.play(anim1).with(anim2);  
animSet.play(anim2).with(anim3);  
animSet.play(anim4).after(anim3);  
animSet.setDuration(1000);  
animSet.start();

3.2 AnimatorInflater类的使用

前面讲View动画和Drawable动画的时候都提到了xml来实现动画的方式,而属性动画也可以通过xml的方式下来实现动画效果,其就是借助了AnimatorInflater这个类来实现。

AnimatorInflater类加载额xml文件放在res/animator/目录下,这里创建一个rotation.xml文件,内容为

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" 
    android:propertyName="rotationX"
    android:duration="1000"
    android:valueType="floatType"
    android:valueFrom="0.0"
    android:valueTo="360.0">
</objectAnimator>

然后借助AnimatorInflater类来加载xml动画

Animator animator = AnimatorInflater.loadAnimator(context, R.animator.rotation);
animator.setTarget(view);
animator.setDuration(2000);
animator.setInterpolator(new LinearInterpolator());
animator.start();

这样便通过使用AnimatorInflater加载xml完成了一个属性动画的操作。

3.3 TypeEvaluator 、 TimeInterpolator这两个类的使用

前面提到TypeEvaluator叫做类型估值器,TimeInterpolator叫做时间插值器,类型估值器用来动态的设置属性变化,而时间插值器用来设置时间相对动画的变化效果。简单的说,TimeInterpolator控制动画的速度,而TypeEvaluator控制动画的值。这两个类的使用比较灵活,可以去参考模拟自然动画的精髓——TimeInterpolator与TypeEvaluator这篇文章,这里举一个模拟抛物线的动画来进行说明。

如果我希望小球抛物线运动【实现抛物线的效果,水平方向100px/s,垂直方向加速度200px/s*s 】,分析一下,貌似只和时间有关系,但是根据时间的变化,横向和纵向的移动速率是不同的,我们该咋实现呢?此时就要重写TypeEvaluator了,因为我们在时间变化的同时,需要返回给对象两个值,x当前位置,y当前位置。

ValueAnimator valueAnimator = new ValueAnimator();  
valueAnimator.setDuration(3000);  
valueAnimator.setObjectValues(new PointF(0, 0));  
valueAnimator.setInterpolator(new LinearInterpolator());  
valueAnimator.setEvaluator(new TypeEvaluator<PointF>()  
{  
    // fraction = t / duration  
    @Override  
    public PointF evaluate(float fraction, PointF startValue, PointF endValue)  
    {  
        Log.e(TAG, fraction * 3 + "");  
        // x值为200 * t ,而y值为0.5 * 10 * t * t  
        PointF point = new PointF();  
        point.x = 200 * fraction * 3;  
        point.y = 0.5f * 10 * (fraction * 3) * (fraction * 3);  
        return point;  
    }  
});  

valueAnimator.start();  
valueAnimator.addUpdateListener(new AnimatorUpdateListener()  
{  
    @Override  
    public void onAnimationUpdate(ValueAnimator animation)  
    {  
        PointF point = (PointF) animation.getAnimatedValue();  
        mBlueBall.setX(point.x);  
        mBlueBall.setY(point.y);  

    }  
});

从代码可以看出重新定义了类型估值器,设置了x y值得变化,同时将时间插值器设置为默认的线性变化,那么最终小球将以抛物线的动画运动。

4、参考文献

本文基本代码都是从其它参考文献拷贝过来,略加修改的,感谢这些作者的辛勤奉献。

1、 Android 属性动画(Property Animation) 完全解析 (上)

2、Android中的View动画和属性动画

3、Android动画之一:Drawable Animation

4、Android 动画学习(一)之View Animation

5、 Android属性动画–基础使用

6、模拟自然动画的精髓——TimeInterpolator与TypeEvaluator

7、Android动画,一篇就够

8、res下的anim和animator文件夹