首页 > 技术文章 > Android Animation(动画)

yishujun 2014-12-10 16:19 原文

前言

Android 平台提供实现动画的解决方案(三种)

一、3.0以前,android支持两种动画:

(1)Frame Animation:顺序播放事先做好的图像,与gif图片原理类似,是一种逐帧动画;

(2)Tween Animation:通过对场景里的对象不断做图像变换(渐变、平移、缩放、旋转)产生动画效果,即是一种补间动画

二、android3.0中又引入了一个新的动画系统:property Animation

(3)Property Animation:通过改变的是对象的实际属性,只是表示一个值在一段时间内的改变,当值改变时要做什么事情完全是你自己决定的。

注意:这三种动画模式在SDK中被称为     property animation      view animation(tween animation)     drawable animation(frame animation)

代码部分示例截图:

D69031486DDC0437412167573020FEBC2C083411CFABF20BF5BAB616C61729EB451373B893DE27EE6561DB522C9F01978C71441ADBA70470AA4E92F40D504E5638C96D2EE1FC18E50A5521547165EEE9

 

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

drawable animation

Drawable Animation(Frame Animation):帧动画,就像GIF图片,通过一系列Drawable依次显示来模拟动画的效果.

实现方式——(代码 | xml):

一、代码:通过Java代码实现Frame Animation动画

(1)要实现Frame Animation动画,需要创建一个AnimationDrawable对象来表示Frame动画,然后通过addFrame()方法把每一帧要显示的内容添加进去,最后通过start()方法就可以播放动画了,

常用方法:

AnimationDrawable类用于创建由一系列Drawable对象构成的逐帧动画对象,它可以作为一个视图对象的背景。

AnimationDrawable类的常用方法有以下一些:

mAnimationDrawable.addFrame(Drawable frame, int duration);//添加一个帧动画

mAnimationDrawable.getDuration(int i);//获得帧动画的时间

mAnimationDrawable.getFrame(int index);//获得指定索引的Drawable对象

mAnimationDrawable.getNumberOfFrames();//获得帧动画的总数

mAnimationDrawable.isOneShot();//帧动画是否只运行一次

mAnimationDrawable.isRunning();//帧动画是否处于运行状态

mAnimationDrawable.setOneShot(boolean onsShot);//设置帧动画是否只运行一次

mAnimationDrawable.setVisible(boolean visible, boolean restart);//设置帧动画是否可见

mAnimationDrawable.start();//运行帧动画

mAnimationDrawable.stop();//停止帧动画

具体实现:

(2)需要预先准备了10张单帧动画图像,分别命名为img_0到img_5,并存放在工程的res/drawable目录下。然后可以通过如下方法将每一帧的图像加载到AnimationDrawable对象中。

AnimationDrawable mAnimationDrawable = new AnimationDrawable();      //AnimationDrawable对象

Drawable mDrawable ;        //Drawable对象

ImageView mImageView;      //展示动画的ImageView 对象

private void setAnimDrawable() {
mAnimationDrawable = new AnimationDrawable();
for (int i = 0; i < 6; i++) {
int resourcesId = getResources().getIdentifier("img_" + i, "mipmap", this.getPackageName()); // 根据资源ID获取到Drawable对象
mDrawable = ContextCompat.getDrawable(this,resourcesId); //根据资源ID获取到Drawable对象
mAnimationDrawable.addFrame(mDrawable, 500); // 将此帧添加到AnimationDrawable中
}
mAnimationDrawable.setOneShot(false); // 如果设置为true,则只会播放一次,不会循环播放。
mImageView.setBackground(mAnimationDrawable); // 将动画设置为ImageView背景
}

mAnimationDrawable.start(); // 开始播放

mAnimationDrawable.stop(); //停止播放

二、xml:通过xml布局文件实现Frame Animation动画

(1)逐帧动画的实现,也可以通过xml布局文件来完成。我们可以放置在/res下的anim或drawable目录中(/res/[anim | drawable]/filename.xml),文件名可以作为资源ID在代码中引用;如果由完全由编码实现,我们需要使用到AnimationDrawable对象。

(2)使用xml来实现Frame动画时,首先可以通过 setBackgroundResource()方法来加载xml动画布局文件,然后通过getBackground()方法获得动画,如果要设置到其他组件的背景可以再通过 setBackgroundDrawable()方法设置要显示的动画,最后通过start()方法来播放动画即可。

XML语法:

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot=["true" | "false"] >
    <item
        android:drawable="@[package:]drawable/drawable_resource_name"
        android:duration="integer" />
</animation-list>

注意:

(1)<animation-list>元素是必须的,并且必须要作为根元素,可以包含一或多个<item>元素;android:onshot如果定义为true的话,此动画只会执行一次,如果为false则一直循环。

(2)<item>元素代表一帧动画,android:drawable指定此帧动画所对应的图片资源,android:druation代表此帧持续的时间,整数,单位为毫秒。

常用属性:

Frame动画的xml文件常用属性如下:

android:drawable[drawable]//加载Drawable对象

android:duration[long]//每一帧动画的持续时间(单位ms)

android:oneshot[boolean]//动画是否只运行一次,true运行一次,false重复运行

android:visible[boolean]//Drawable对象的初始能见度状态,true可见,false不可见(默认为false)

具体实现:

AnimationDrawable mAnimationDrawable; //AnimationDrawable对象 Drawable mDrawable; //Drawable对象 ImageView mImageView;

      //展示动画的

ImageView

对象

mImageView.setBackgroundResource(R.anim.frame);    // 指定动画的帧的列表
mAnimationDrawable= (AnimationDrawable) imageView.getBackground(); // AnimationDrawable--与逐帧动画相关的Drawable

//

mImageViewOther.setBackgroundDrawable(mAnimationDrawable);

   //如果需要设置在其他组件上面可以直接这样设置

mAnimationDrawable.start(); // 开始播放

mAnimationDrawable.stop(); //停止播放

frame_animation.xml源代码:
<?xml version="1.0" encoding="utf-8"?>
<animation-list
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false"    >

    <item android:drawable="@drawable/img_0"    android:duration="1000"    /> 
    <item android:drawable="@drawable/img_1"    android:duration="1000"    />
    <item android:drawable="@drawable/img_2"    android:duration="1000"    />
    <item android:drawable="@drawable/img_3"    android:duration="1000"    />
    <item android:drawable="@drawable/img_4"    android:duration="1000"    />
    <item android:drawable="@drawable/img_5"    android:duration="1000"    />

</animation-list>

问题总结:

(1)要在代码中调用Imageview的setBackgroundResource方法,如果直接在XML布局文件中设置其src属性当触发动画时会FC。

(2)在动画start()之前要先stop(),不然在第一次动画之后会停在最后一帧,这样动画就只会触发一次。

(3)最后一点是SDK中提到的,不要在onCreate中调用start,因为AnimationDrawable还没有完全跟Window相关联,如果想要界面显示时就开始动画的话,可以在onWindowFoucsChanged()中调用start()。

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

view animation

(1)view animation(tween animation)通过对场景里的对象不断做图像变换(渐变、平移、缩放、旋转)产生动画(通过算法将给定属性值在给定的时间内在两个关键帧间渐变)效果

(2)Tween动画在Android中分为4类,它们分别是:AlphaAnimation(透明度动画)、TranslateAnimation(平移动画)、ScaleAnimation(缩放动画)、RotateAnimation(旋转动画),都继承自android.view.Animation 类

(3)表示从一个状态A向状态B变化的一个过程,所以英文名字叫Tween动画、中文名叫:“补间动画”、“中间动画”。它们总的说来有两种实现方式:java code(java源代码)、xml(xml配置文件)

注意:

(1)View animation只能应用于View对象,而且只支持一部分属性,如支持缩放旋转而不支持背景颜色的改变。

(2)View Animation只是改变了View对象绘制的位置,而没有改变View对象本身,比如,你有一个Button,坐标(100,100),Width:200,Height:50,而你有一个动画使其变为Width:100,Height:100,你会发现动画过程中触发按钮点击的区域仍是(100,100)-(300,150)。

(3)View Animation就是一系列View形状的变换,如大小的缩放,透明度的改变,位置的改变,动画的定义既可以用代码定义也可以用XML定义,当然,建议用XML定义。

(4)可以给一个View同时设置多个动画,比如从透明至不透明的淡入效果,与从小到大的放大效果,这些动画可以同时进行,也可以在一个完成之后开始另一个。

(5)用XML定义的动画放在/res/anim/文件夹内。

实现方式——(代码 | xml):

一、代码:通过Java代码实现tween Animation动画

AlphaAnimation(透明度动画)

AlphaAnimation有两个构造函数,分别是:

                      —— AlphaAnimation(Context context, AttributeSet attrs):

                              第二个参数是个属性集,之后会详细对AttributeSet 讲解

                       ——AlphaAnimation(float fromAlpha, float toAlpha):

                             第一个参数是初始透明度(取值范围为0.0到1.0)

                             第二个参数是终止透明度

 

TranslateAnimation(平移动画)

TranslateAnimation有三个构造函数,分别是:

                       ——TranslateAnimation(Context context, AttributeSet attrs):略过

                       ——TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta):

                             分别对应x轴的起始、终点坐标,与y轴的起始、终点坐标

                      ——TranslateAnimation(int fromXType, float fromXValue, int toXType, float toXValue, int fromYType, float fromYValue, int toYType, float toYValue):

                             第一个参数是x轴方向的值的参照(Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or Animation.RELATIVE_TO_PARENT)

                             第二个参数是第一个参数类型的起始值

                             第三个参数与第四个参数是x轴方向的终点参照与对应值

                             后面四个参数就不用解释了。如果全部选择Animation.ABSOLUTE,其实就是第二个构造函数。

                              以x轴为例介绍参照与对应值的关系

                              如果选择参照为Animation.ABSOLUTE,那么对应的值应该是具体的坐标值,比如100到300,指绝对的屏幕像素单位

                              如果选择参照为Animation.RELATIVE_TO_SELF或者 Animation.RELATIVE_TO_PARENT指的是相对于自身或父控件,

                              对应值应该理解为相对于自身或者父控件的几倍或百分之多少。一定要多试试这几个参数类型!

ScaleAnimation(缩放动画)

ScaleAnimation(缩放动画)有四个构造函数,分别是:

                       ——ScaleAnimation(Context context, AttributeSet attrs):略过

                       ——ScaleAnimation(float fromX, float toX, float fromY, float toY):同TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta)

                       ——ScaleAnimation(float fromX, float toX, float fromY, float toY, float pivotX, float pivotY):这里解释后面两个参数,pivo英文意思为“枢轴”,也就是支点。通过这两个参数可以控制缩放动画的放大方向,这个点不会随对象大小变化而变化

                      ——ScaleAnimation(float fromX, float toX, float fromY, float toY, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue):如果理解了前面所讲的,这个就不做多的说明,如果不清楚,请回头多用代码试试。

RotateAnimation(旋转动画)

RotateAnimation(旋转动画)同样有四个构造函数,分别是:

                      ——RotateAnimation(Context context, AttributeSet attrs)

                     ——RotateAnimation(float fromDegrees, float toDegrees)

                     ——RotateAnimation(float fromDegrees, float toDegrees, float pivotX, float pivotY)

                     ——RotateAnimation(float fromDegrees, float toDegrees, int pivotXType, float pivotXValue, int pivotYType, float  pivotYValue)

                     (pivotX,pivotY)为旋转点。pivotX为距离左侧的偏移量,pivotY为距离顶部的偏移量。即为相对于View左上角(0,0)

Animation常用方法:

setDuration(long durationMillis):设置动画持续事件(单位:毫秒)
setFillAfter(boolean fillAfter):如果fillAfter设为true,则动画执行后,控件将停留在动画结束的状态
setFillBefore(boolean fillBefore):如果fillBefore设为true,则动画执行后,控件将回到动画开始的状态
setStartOffset(long startOffset):设置动画执行之前等待的时间(单位:毫秒)
setRepeatCount(int repeatCount):设置动画重复的次数
setInterpolator(Interpolator i):设置动画的变化速度
setInterpolator(new AccelerateDecelerateInterpolator()):先加速,后减速
setInterpolator(new AccelerateInterpolator()):加速
setInterpolator(new DecelerateInterpolator()):减速
setInterpolator(new CycleInterpolator()):动画循环播放特定次数,速率改变沿着正弦曲线
setInterpolator(new LinearInterpolator()):匀速

二、xml:通过xml布局文件实现tween  Animation动画

(1)XML文件的根元素可以为<alpha>,<scale>,<translate>,<rotate>,interpolator 元素或<set>(表示以上几个动画的集合,set可以嵌套)。默认情况下,所有动画是同时进行的,可以通过startOffset属性设置各个动画的开始偏移(开始时间)来达到动画顺序播放的效果

(2)可以通过设置interpolator属性改变动画渐变的方式,如AccelerateInterpolator,开始时慢,然后逐渐加快。默认为AccelerateDecelerateInterpolator。

具体实现:

定义好动画的XML文件后,可以通过类似下面的代码对指定View应用动画 tween Animation xml定义请移步http://www.cnblogs.com/yishujun/p/5407711.html

mAnimation = AnimationUtils.loadAnimation(this.getContext(), R.anim.rotate_anim);   //初始化动画

view.startAnimation(mAnimation );  //给view设置动画

补充:

注意: 以上都是单独的使用某个动画,那么如何让多个动画同时生效呢?答案是 AnimationSet, 该类也是继承自 Animation的。默认情况下,所有动画是同时进行的,可以通过setStartOffset属性设置各个动画的开始偏移(开始时间)来达到动画顺序播放的效果

AnimationSet的简单使用:

//初始化 TranslateAnimation动画 

translateAnimation = …;

//初始化 Alpha动画 

alphaAnimation = …;

//动画集 

AnimationSet set = new AnimationSet(true); 

set.addAnimation(translateAnimation);  

set.addAnimation(alphaAnimation);  

//设置动画时间 (作用到每个动画) 

set.setDuration(3000); 

view.startAnimation(set); 

AnimationSet和 AnimatorSet简单区别:

AnimationSet和 AnimatorSet都是动画集合。这里简单介绍下他们的异同,了解这些后在设计动画实现时才能得心应手。
AnimationSet 我们最常用的是调用其 addAnimation 将一个个不一样的动画组织到一起来,然后调用view 的 startAnimation 方法触发这些动画执行。功能较弱不能做到把集合中的动画按一定顺序进行组织然后在执行的定制。
AnimatorSet 我们最常用的是调用其play、before、with、after 等方法设置动画的执行顺序,然后调用其start 触发动画执行。
AnimationSet 与 AnimatorSet 最大的不同在于,AnimationSet 使用的是 Animation 子类、AnimatorSet 使用的是 Animator 的子类。
Animation 是针对视图外观的动画实现,动画被应用时外观改变但视图的触发点不会发生变化,还是在原来定义的位置。
Animator  是针对视图属性的动画实现,动画被应用时对象属性产生变化,最终导致视图外观变化。

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

property animation

这个是在Android 3.0中才引进的,它更改的是对象的实际属性,在View Animation(Tween Animation)中,其改变的是View的绘制效果,真正的View的属性保持不变,比如无论你在对话中如何缩放Button的大小,Button的有效点击区域还是没有应用动画时的区域,其位置与大小都不变。而在Property Animation中,改变的是对象的实际属性,如Button的缩放,Button的位置与大小属性值都改变了。而且Property Animation不止可以应用于View,还可以应用于任何对象。Property Animation只是表示一个值在一段时间内的改变,当值改变时要做什么事情完全是你自己决定的。

在Property Animation中,可以对动画应用以下属性:

  • Duration:动画的持续时间
  • TimeInterpolation:属性值的计算方式,如先快后慢
  • TypeEvaluator:根据属性的开始、结束值与TimeInterpolation计算出的因子计算出当前时间的属性值
  • Repeat Country and behavoir:重复次数与方式,如播放3次、5次、无限循环,可以此动画一直重复,或播放完时再反向播放
  • Animation sets:动画集合,即可以同时对一个对象应用几个动画,这些动画可以同时播放也可以对不同动画设置不同开始偏移
  • Frame refreash delay:多少时间刷新一次,即每隔多少时间计算一次属性值,默认为10ms,最终刷新时间还受系统进程调度与硬件的影响

推荐文章:http://blog.csdn.net/guolin_blog/article/details/43536355http://www.mamicode.com/info-detail-1150209.htmlhttp://www.cnblogs.com/mengdd/p/3301256.html

ValueAnimator

ValueAnimator是属性动画中的一个重要的类,其内部使用一种时间循环的机制来计算值与值之间的动画过渡,我们只需要将初始值和结束值提供给 ValueAnimator,并且告诉它动画所需运行的时长,那么ValueAnimator就会自动帮我们完成从初始值平滑地过渡到结束值这样的效果

(1)ValueAnimator 可以描叙一些整型、浮点型或颜色型值变化,ValueAnimator类可以让你为这些类型的属性值设置动画。

(2)可以通过如下的一些工厂方法来获取ValueAnimator实例:ofInt()、ofFloat()或者ofObject,

理解参数

 ValueAnimator ofInt(int... values)   
 ValueAnimator ofArgb(int... values)
 ValueAnimator ofFloat(float... values) 
 ValueAnimator ofPropertyValuesHolder(PropertyValuesHolder... values)
 ValueAnimator ofObject(TypeEvaluator evaluator, Object... values) 

示例1:

ValueAnimator animation = ValueAnimator.ofFloat(0f, 1f);
animation.setDuration(2000);
animation.start();

当start方法调用的时候,ValueAnimator 在0和1之间计算动画的值(这个计算工作就是由ValueAnimator帮助我们完成),持续时间是2000ms,理论上可以理解成把0到1这个时间片段 分成2000份,在每一份中我们可以做相应的动作,比如慢慢移动图片(实际上是多份为一组值或者隔很多份取一个值value=getAnimatedValue)

示例2

ValueAnimator anim = ValueAnimator.ofFloat(0f, 5f, 3f, 10f); anim.setDuration(5000); anim.start();当有多个参数的时候如上可以理解将一个值在5秒内从0过渡到5,再过渡到3,再过渡到10

示例2:

ValueAnimator animation = ValueAnimator.ofObject(new MyTypeEvaluator(), startPropertyValue, endPropertyValue);
animation.setDuration(2000);
animation.start();
在上面的代码中,当start方法调用的时候,ValueAnimator 在startPropertyValue和endPropertyValue之间使用MyTypeEvaluator计算属性值,持续时间是2000ms

上面的示例代码片段不会对一个对象产生实际的影响,这时因为ValueAnimator并不会直接作用在对象或属性上。如过想修改某个对象的相应属性(移动图片,图片距离屏幕左边距离),最好的办法是在计算他们值的时候修改他们你可以在ValueAnimator中通过定义监听器来在动画的持续过程中处理重要的事件。当你实现这些监听器的时候,你可以通过调用getAnimatedValue()来获取当前帧计算后的值

注意:

(1)我们还可以调用setStartDelay()方法来设置动画延迟播放的时间,调用setRepeatCount()和setRepeatMode()方法来设置动画循环播放的次数以及循环播放的模式,循环模式包括RESTART和REVERSE两种,分别表示重新播放和倒序播放的意思。这些方法都很简单

(2)由于我们要进行动画处理的值是各种各样的,可能不是float、int或颜色值,那我们怎么使用属性动画呢?为此,ValueAnimator提供了一个ofObject方法,该方法接收一个TypeEvaluator类型的参数,我们需要实现该接口 TypeEvaluator的evaluate方法,只要我们实现了TypeEvaluator接口,我们就能通过ofObject方法处理任意类型的数据,相比ValueAnimator类,ObjectAnimator更加实用,因为它真正可以作用在一个对象上。不过ObjectAnimator是继承自ValueAnimator的,所以主体方法还是ValueAnimator里实现的

推荐文章:http://blog.csdn.net/feiduclear_up/article/details/45893619

ObjectAnimator

ObjectAnimator继承自ValueAnimator。我们之前提到,要让属性动画渐变式地更改对象中某个属性的值,可分两步操作:第一步,动画需要计算出某一时刻属性值应该是多少;第二步,需要将计算出的属性值赋值给动画的属性。 ValueAnimator只实现了第一步,也就是说ValueAnimator只负责以动画的形式不断计算不同时刻的属性值,但需要我们开发者自己写代码在动画监听器AnimatorUpdateListener的onAnimationUpdate方法中将计算出的值通过对象的setXXX等方法更新对象的属性值。ObjectAnimator比ValueAnimator更进一步,其会自动调用对象的setXXX方法更新对象中的属性值。

常用设置方法:

  1. setInterpolator():设置动画插值
  2. setDuration():设置动画执行时间
  3. setRepeatCount():设置动画重复次数
  4. setRepeatMode():设置动画重复模式 ,

          RESTART:重新从头开始执行。

         REVERSE:反方向执行。

  5. setStartDelay():设置动画延时操作
  6. setTarget():设置动画的对象
  7. setEvaluator():设置动画过度的评估者。

推荐文章:http://blog.csdn.net/feiduclear_up/article/details/45915377

关于property animation的具体使用请参考示例

AnimatorSet(组合动画)

上面我们看到的都是单个动画,那么需要实现组合动画怎么办呢?不着急,Android工程师给我们提供了两种方法来实现,AnimatorSet类,ObjectAnimator.ofPropertyValuesHolder()方法。

after(Animator anim) 将现有动画插入到传入的动画之后执行
after(long delay) 将现有动画延迟指定毫秒后执行
before(Animator anim) 将现有动画插入到传入的动画之前执行
with(Animator anim) 将现有动画和传入的动画同时执行

xml文件动画

请移步到推荐文章,写得非常好

推荐文章:http://www.cnblogs.com/mengdd/p/3303403.html

补充

在 Android 3.0 中给 View 增加了一些新的属性

在 Android 3.0 中给 View 增加了一些新的属性以及相应的 getter、setter 方法。Property Animation系统可以通过修改 View 对象实际的属性值来实现屏幕上的动画效果。此外,当属性值发生变化时,Views 也会自动调用 invalidate() 方法来刷新屏幕。 View 类中新增的便于实现 property 动画的属性包括:

     (1) translationX 和 translationY:这两个属性控制着 View 的屏幕位置坐标变化量,以 layout 容器的左上角为坐标原点;
     (2) rotation、rotationX 和 rotationY:这三个属性控制着 2D 旋转角度(rotation属性)和围绕某枢轴点的 3D 旋转角度;
     (3) scaleX、scaleY:这两个属性控制着 View 围绕某枢轴点的 2D 缩放比例;
     (4) pivotX 和 pivotY: 这两个属性控制着枢轴点的位置,前述的旋转和缩放都是以此点为中心展开的,缺省的枢轴点是 View 对象的中心点;
     (5) x 和 y:这是指 View 在容器内的最终位置,等于 View 左上角相对于容器的坐标加上 translationX 和 translationY 后的值;
     (6)alpha:表示 View 的 alpha 透明度。缺省值为 1 (不透明),为 0 则表示完全透明(看不见);
要动画显示 View 对象的某个属性,比如颜色或旋转值,我们所有要做的事情就是创建一个 Property animation,并设定对应的 View 属性。那接下来我们就用ObjectAnimator类来分别实现View的透明度渐变、收缩、移动和旋转等动画效果。

 

示例代码源码下载

推荐阅读