基于OPhone 2.0的2D动画实践(一)


本系列文章主要介绍了OPhone 2.0 SDK提供的两种实现2D动画的方式:帧动画和补间动画。文章的每个知识点都提供了精彩的实例以向读者展示2D动画的具体实现方法。通过对本系列文章的学习,读者可利用2D动画实现非常绚丽的界面效果。

相关阅读:

基于OPhone 2.0的2D动画实践(一)

基于OPhone 2.0的2D动画实践(二)

基于OPhone 2.0的2D动画实践(三)
 

  帧动画简介
  如果读者使用过Flash,一定对帧动画非常熟悉。帧动画实际上就是由若干图像组成的动画。这些图像会以一定的时间间隔进行切换。电影的原理也有些类似于帧动画。一般电影是每秒25帧,也就是说,电影在每秒钟内会以相等的时间间隔连续播放25幅电影静态画面。由于人的视觉暂留,在这样的播放频率下,看起来电影才是连续的。在onDraw方法中使用invalidate方法不断刷新View的方式实现旋转动画。实际上,这也相当于帧动画,只是并不是利用若干静态图像的不断切换来制作帧动画,而是不断地画出帧动画中的每一帧图像。


  AnimationDrawable与帧动画
  OPhone中的帧动画需要在一个动画文件中指定动画中的静态图像和每一张静态图像停留的时间(单位:毫秒)。一般可以将所有图像的停留时间设为同一个值。动画文件采用了XML格式。该文件需要放在res\anim目录中。让我们先来建立一个简单的动画文件,首先在res\anim目录中建立一个test.xml文件,然后输入如下的内容:

 
  1.   <animation-list xmlns:Android="http://schemas.android.com/apk/res/android" android:oneshot="false">   <item android:drawable="@drawable/anim1" android:duration="50" />   <item android:drawable="@drawable/anim2" android:duration="50" />   <item android:drawable="@drawable/anim3" android:duration="50" />   <item android:drawable="@drawable/anim4" android:duration="50" />   <item android:drawable="@drawable/anim5" android:duration="50" />   </animation-list>  

  从anim.xml文件的内容可以看出,一个标准的动画文件由一个<animation-list>标签和若干<item>标签组成。其中<animation-list>标签的一个关键属性是android:oneshot,如果该属性值为true,表示帧动画只运行一遍,也就是从第1个图像切换到最后一个图像后,动画就会停止。如果该属性值为false,表示帧动画循环播放。android:oneshot是可选属性,默认值是false。
  <item>标签的android:drawable属性指定了动画中的静态图像资源ID。帧动画播放的顺序就是<item>标签的定义顺序。android:duration属性指定了每个图像的停留时间。在test.xml文件中指定了每个图像的停留时间为50毫秒。android:drawable和android:duration都是必选属性,不能省略。
  编写完动画文件后,就需要装载动画文件,并创建AnimationDrawable对象。AnimationDrawable是Drawable的子类,并在Drawable的基础上提供了控制动画的功能。读者可以使用如下的代码来根据test.xml文件创建AnimationDrawable对象。

 
  1.   AnimationDrawable animationDrawable =   
  2.   (AnimationDrawable)getResources().getDrawable(R.anim.test);  
  在创建完AnimationDrawable对象后,可以使用下面的代码将AnimationDrawable对象作为ImageView组件的背景。  
  1.   ImageView ivAnimView = (ImageView) findViewById(R.id.ivAnimView);   
  2.   ivAnimView.setBackgroundDrawable(animationDrawable);  
 除了可以使用getDrawable方法装载test.anim文件外,还可以使用setBackgroundResource方法装载test.xml文件,并通过getBackground方法获得AnimationDrawable对象,代码如下:  
  1.   ImageView ivAnimView = (ImageView) findViewById(R.id.ivAnimView);   
  2.   ivAnimView.setBackgroundResource(R.anim.test);   
  3.   Object backgroundObject = ivAnimView.getBackground();   
  4.   animationDrawable = (AnimationDrawable) backgroundObject;  
 有了AnimationDrawable对象,就可以通过AnimationDrawable类的方法来控制帧动画。AnimationDrawable类中与帧动画相关的方法如下:
   start:开始播放帧动画。
   stop:停止播放帧动画。
   setOneShot:设置是否只播放一遍帧动画。该方法的参数值与动画文件中的<animation-list>标签的android:oneshot属性值的含义相同。参数值为true表示只播放一遍帧动画,参数值为false表示循环播放帧动画。默认值为false。
   addFrame:向AnimationDrawable对象中添加新的帧。该方法有两个参数,第1个参数是一个Drawable对象,表示添加的帧。该参数值可以是静态图像,也可以是另一个动画。第2个参数表示新添加的帧的停留时间。如果新添加的帧是动画。那么这个停留时间就是新添加的动画可以播放的时间。如果到了停留时间,不管新添加的动画是否播放完,都会切换到下一个静态图像或动画。
   isOneShot:判断当前帧动画是否只播放一遍。该方法返回通过setOneShot方法或android:oneshot属性设置的值。
   isRunning:判断当前帧动画是否正在播放。如果返回true,表示帧动画正在播放。返回false表示帧动画已停止播放。
   getNumberOfFrames:返回动画的帧数,也就是<animation-list>标签中的<item>标签数。
   getFrame:根据帧索引获得指定的帧的Drawable对象。帧从0开始。
   getDuration:获得指定帧的停留时间。
  如果想显示半透明的帧动画,可以通过Drawable类的setAlpha方法设置图像的透明度,该方法只有一个int类型的值,该值的范围是0至255。如果参数值是0,表示图像完全透明,如果参数值是255,表示图像完全不透明。

  通过帧动画方式播放Gif动画
  OPhone SDK中播放GIF动画的类库可能是因为GIF文件版本的问题,并不能播放所有的GIF动画文件,但我们可以采用帧动画的方式来播放GIF动画。
  GIF动画文件本身由多个静态的GIF图像组成,因此,可以使用图像处理软件(如FireWorks)将GIF动画文件分解成多个GIF静态图像。然后将这些文件在res\anim目录中的动画文件中定义。frame_animation.xml文件的代码如下:

 
  1.   <animation-list xmlns:android="http://schemas.android.com/apk/res/android"  
  2.    android:oneshot="false" >   
  3.    <item android:drawable="@drawable/anim1" android:duration="50" />   
  4.    <item android:drawable="@drawable/anim2" android:duration="50" />   
  5.   </animation-list>  
  为了演示在原有动画的基础上添加新的动画,本例引入了第2个GIF动画文件,并将这个GIF动画文件分解成6个GIF静态图像(文件名从myanim1.gif至myanim6.gif)。定义这6个GIF文件的动画文件是frame_animation1.xml。
  本例的功能包含了"开始动画"、"停止动画"、"运行一次动画"和"添加动画",这4个功能分别对应于4个按钮。当单击【开始动画】按钮后,动画开始播放,如图1所示。单击【添加动画】按钮,播放完第1个动画后,又会继续播放第2个动画,如图2所示。在播放完第2个动画后,又会继续播放第1个动画。

  图1  播放第1个动画

  图2  播放第2个动画


  本例的完整代码如下:

  1.   package net.blogjava.mobile;   
  2.   
  3.   import android.app.Activity;   
  4.   import android.graphics.drawable.AnimationDrawable;   
  5.   import android.os.Bundle;   
  6.   import android.view.View;   
  7.   import android.view.View.OnClickListener;   
  8.   import android.widget.Button;   
  9.   import android.widget.ImageView;   
  10.   
  11.   public class Main extends Activity implements OnClickListener   
  12.   {   
  13.   private ImageView ivAnimView;   
  14.   private AnimationDrawable animationDrawable;   
  15.   private AnimationDrawable animationDrawable1;   
  16.   private Button btnAddFrame;   
  17.   @Override  
  18.   public void onClick(View view)   
  19.   {   
  20.   switch (view.getId())   
  21.   {   
  22.   //  只播放一次动画   
  23.   case R.id.btnOneShot:             
  24.   animationDrawable.setOneShot(true);   
  25.   animationDrawable.start();   
  26.   break;   
  27.   //  循环播放动画   
  28.   case R.id.btnStartAnim:   
  29.   animationDrawable.setOneShot(false);   
  30.   animationDrawable.stop();   
  31.   animationDrawable.start();   
  32.   break;   
  33.   //  停止播放动画   
  34.   case R.id.btnStopAnim:   
  35.   animationDrawable.stop();   
  36.   if (animationDrawable1 != null)   
  37.   {   
  38.   //  停止新添加的动画   
  39.   animationDrawable1.stop();   
  40.   }   
  41.   break;   
  42.   //  添加动画   
  43.   case R.id.btnAddFrame:   
  44.   if (btnAddFrame.isEnabled())   
  45.   {   
  46.   //  获得新添加动画的AnimationDrawable对象   
  47.   animationDrawable1 = (AnimationDrawable) getResources()   
  48.   .getDrawable(R.anim.frame_animation1);   
  49.   //  添加动画,动画停留(播放)时间是2秒   
  50.   animationDrawable.addFrame(animationDrawable1, 2000);   
  51.   btnAddFrame.setEnabled(false);   
  52.   }   
  53.   break;   
  54.   }   
  55.   }   
  56.   @Override  
  57.   public void onCreate(Bundle savedInstanceState)   
  58.   {   
  59.   super.onCreate(savedInstanceState);   
  60.   setContentView(R.layout.main);   
  61.   Button btnStartAnim = (Button) findViewById(R.id.btnStartAnim);   
  62.   Button btnStopAnim = (Button) findViewById(R.id.btnStopAnim);   
  63.   Button btnOneShot = (Button) findViewById(R.id.btnOneShot);   
  64.   btnAddFrame = (Button) findViewById(R.id.btnAddFrame);   
  65.   btnStartAnim.setOnClickListener(this);   
  66.   btnStopAnim.setOnClickListener(this);   
  67.   btnOneShot.setOnClickListener(this);   
  68.   btnAddFrame.setOnClickListener(this);   
  69.   ivAnimView = (ImageView) findViewById(R.id.ivAnimView);   
  70.   ivAnimView.setBackgroundResource(R.anim.frame_animation);   
  71.   Object backgroundObject = ivAnimView.getBackground();   
  72.   animationDrawable = (AnimationDrawable) backgroundObject;           
  73.   }   
  74.   }  
  总结
  本文主要介绍了帧动画的原理,并介绍了如何利用OPhone SDK中的API加载并运行帧动画。最后给出了一个例子来用帧动画的方式播放gif动画。

相关内容