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

基于OPhone 2.0的2D动画实践(三)
OPhone平台开发, 2010-10-19 14:12:28
标签 : 动画 2D OPhone2.0

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

  旋转补间动画
  通过<rotate>标签可以定义旋转补间动画。下面的代码定义了一个标准的旋转补间动画。
 

view plaincopy to clipboardprint?
<rotate xmlns:android="http://schemas.android.com/apk/res/android
  android:interpolator="@anim/linear_interpolator" android:fromDegrees="0" 
  android:toDegrees="360" android:pivotX="50%" android:pivotY="50%" 
  android:duration="10000" android:repeatMode="restart" android:repeatCount="infinite"/> 

<rotate xmlns:android="http://schemas.android.com/apk/res/android"   android:interpolator="@anim/linear_interpolator" android:fromDegrees="0"   android:toDegrees="360" android:pivotX="50%" android:pivotY="50%"   android:duration="10000" android:repeatMode="restart" android:repeatCount="infinite"/>
  其中<rotate>标签有两个特殊的属性。它们的含义如下:
   android:fromDegrees:表示旋转的起始角度。
   android:toDegrees:表示旋转的结束角度。
  在<rotate>标签中还使用如下两个属性设置旋转的次数和模式。
   android:repeatCount:设置旋转的次数。该属性需要设置一个整数值。如果该值为0,表示不重复显示动画。也就是说,对于上面的旋转补间动画,只从0度旋转到360度,动画就会停止。如果属性值大于0,动画会再次显示该属性指定的次数。例如,如果android:repeatCount属性值为1。动画除了正常显示一次外,还会再显示一次。也就是说,前面的旋转补间动画会顺时针自转两周。如果想让补间动画永不停止,可以将android:repeatCount属性值设为"infinite"或-1。该属性的默认值是0。
   android:repeatMode:设置重复的模式。默认值是restart。该属性只有当android:repeatCount设置成大于0的数或infinite才起作用。android:repeatMode属性值除了可以是restart外,还可以设为reverse,表示偶数次显示动画时会做与动画文件定义的方向相反的动作。例如,上面定义的旋转补间动画会在第1、3、5、...、2n - 1圈顺时针旋转,而在2、4、6、...、2n圈逆时针旋转。如果想使用Java代码来设置该属性,可以使用Animation类的setRepeatMode方法。该方法只接收一个int类型参数。可取的值是Animation.RESTART和Animation.REVERSE。
  如果想通过Java代码实现旋转补间动画,可以创建android.view.animation.RotateAnimation对象。RotateAnimation类构造方法的定义如下:
 

view plaincopy to clipboardprint?
public RotateAnimation(float fromDegrees, float toDegrees, float pivotX, float pivotY); 

public RotateAnimation(float fromDegrees, float toDegrees, float pivotX, float pivotY);
  通过RotateAnimation类的构造方法可以设置旋转开始角度(fromDegrees)、旋转结束角度(toDegrees)、旋转支点横坐标(pivotX)和旋转支点纵坐标(pivotY)。


  旋转补间动画实例
  本例实现了两颗行星绕着一颗恒星旋转的效果。其中恒星会顺时针和逆时针交替旋转(android:repeatMode属性值为reverse)。效果如图1所示。

 

  图1  旋转的星系
 

  两颗行星和一颗恒星分别对应于一个动画文件。行星对应的两个动画文件的内容如下:

view plaincopy to clipboardprint?
hesper.xml  
  <rotate xmlns:android="http://schemas.android.com/apk/res/android
  android:interpolator="@anim/linear_interpolator" android:fromDegrees="0" 
  android:toDegrees="360" android:pivotX="200%" android:pivotY="300%" 
  android:duration="5000" android:repeatMode="restart" android:repeatCount="infinite"/> 

hesper.xml   <rotate xmlns:android="http://schemas.android.com/apk/res/android"   android:interpolator="@anim/linear_interpolator" android:fromDegrees="0"   android:toDegrees="360" android:pivotX="200%" android:pivotY="300%"   android:duration="5000" android:repeatMode="restart" android:repeatCount="infinite"/>
 

view plaincopy to clipboardprint?
earth.xml  
  <rotate xmlns:android="http://schemas.android.com/apk/res/android
  android:interpolator="@anim/linear_interpolator" android:fromDegrees="0" 
  android:toDegrees="360" android:pivotX="200%" android:pivotY="300%" 
  android:duration="10000" android:repeatMode="restart" android:repeatCount="infinite"/> 

earth.xml   <rotate xmlns:android="http://schemas.android.com/apk/res/android"   android:interpolator="@anim/linear_interpolator" android:fromDegrees="0"   android:toDegrees="360" android:pivotX="200%" android:pivotY="300%"   android:duration="10000" android:repeatMode="restart" android:repeatCount="infinite"/>
  恒星对应的动画文件的内容如下:

view plaincopy to clipboardprint?
sun.xml  
  <rotate xmlns:android="http://schemas.android.com/apk/res/android
  android:interpolator="@anim/linear_interpolator" android:fromDegrees="0" 
  android:toDegrees="360" android:pivotX="50%" android:pivotY="50%" 
  android:duration="20000" android:repeatMode="reverse" android:repeatCount="infinite"/> 

sun.xml   <rotate xmlns:android="http://schemas.android.com/apk/res/android"   android:interpolator="@anim/linear_interpolator" android:fromDegrees="0"   android:toDegrees="360" android:pivotX="50%" android:pivotY="50%"   android:duration="20000" android:repeatMode="reverse" android:repeatCount="infinite"/>
  本例的主程序相对简单,只需要装载这3个动画文件,并开始动画即可,代码如下:
 

view plaincopy to clipboardprint?
package net.blogjava.mobile;  
 
  import android.app.Activity;  
  import android.os.Bundle;  
  import android.view.animation.Animation;  
  import android.view.animation.AnimationUtils;  
  import android.widget.ImageView;  
 
  public class Main extends Activity  
  {  
  @Override 
  public void onCreate(Bundle savedInstanceState)  
  {  
  super.onCreate(savedInstanceState);  
  setContentView(R.layout.main);  
  ImageView ivEarth = (ImageView) findViewById(R.id.ivEarth);  
  ImageView ivHesper = (ImageView) findViewById(R.id.ivHesper);  
  ImageView ivSun = (ImageView) findViewById(R.id.ivSun);  
  Animation earthAnimation = AnimationUtils.loadAnimation(this,R.anim.earth);  
  Animation hesperAnimation = AnimationUtils.loadAnimation(this,R.anim.hesper);  
  Animation sunAnimation = AnimationUtils.loadAnimation(this, R.anim.sun);  
  ivEarth.startAnimation(earthAnimation);  
  ivHesper.startAnimation(hesperAnimation);  
  ivSun.startAnimation(sunAnimation);  
  }  
  } 

package net.blogjava.mobile;   import android.app.Activity;   import android.os.Bundle;   import android.view.animation.Animation;   import android.view.animation.AnimationUtils;   import android.widget.ImageView;   public class Main extends Activity   {   @Override   public void onCreate(Bundle savedInstanceState)   {   super.onCreate(savedInstanceState);   setContentView(R.layout.main);   ImageView ivEarth = (ImageView) findViewById(R.id.ivEarth);   ImageView ivHesper = (ImageView) findViewById(R.id.ivHesper);   ImageView ivSun = (ImageView) findViewById(R.id.ivSun);   Animation earthAnimation = AnimationUtils.loadAnimation(this,R.anim.earth);   Animation hesperAnimation = AnimationUtils.loadAnimation(this,R.anim.hesper);   Animation sunAnimation = AnimationUtils.loadAnimation(this, R.anim.sun);   ivEarth.startAnimation(earthAnimation);   ivHesper.startAnimation(hesperAnimation);   ivSun.startAnimation(sunAnimation);   }   }
  透明度补间动画
  通过<alpha>标签可以定义透明度补间动画。下面的代码定义了一个标准的透明度补间动画。

view plaincopy to clipboardprint?
<alpha xmlns:android="http://schemas.android.com/apk/res/android
      android:interpolator="@android:anim/accelerate_interpolator" 
  android:fromAlpha="1.0" android:toAlpha="0.1" android:duration="2000" /> 

<alpha xmlns:android="http://schemas.android.com/apk/res/android"    android:interpolator="@android:anim/accelerate_interpolator"   android:fromAlpha="1.0" android:toAlpha="0.1" android:duration="2000" />
  其中android:fromAlpha和android:toAlpha属性分别表示起始透明度和结束透明度。这两个属性的值都在0.0和1.0之间。属性值为0.0表示完全透明,属性值为1.0表示完全不透明。
  如果想通过Java代码实现透明度补间动画,可以创建android.view.animation.AlphaAnimation对象。AlphaAnimation类构造方法的定义如下:

view plaincopy to clipboardprint?
public AlphaAnimation(float fromAlpha, float toAlpha); 

public AlphaAnimation(float fromAlpha, float toAlpha);
  通过AlphaAnimation类的构造方法可以设置起始透明度(fromAlpha)和结束透明度(toAlpha)


  透明度补间动画实例
  本例将前面介绍的多种动画效果进行结合实现了投掷炸1弹,并爆炸的特效。在本例中采用的动画类型有帧动画、移动补间动画、缩放补间动画和透明度补间动画。
  其中使用了帧动画播放了一个爆炸的GIF动画;使用移动补间动画实现了炸1弹被投下仍然会向前移动的偏移效果;缩放补间动画实现了当炸1弹被投下时逐渐缩小的效果。透明度补间动画实现了炸1弹被投下时逐渐模糊的效果。当运行本例后,会在屏幕下方正中间显示一个炸1弹,如图2所示。然后触摸这个炸1弹,炸1弹开始投掷,逐渐变小和模糊,如图3所示。当炸1弹变得很小、很模糊时,会播放GIF动画来显示爆炸效果,并播放爆炸的声音。如图4所示。

 

  图2  初始状态的炸1弹

  

  图3 炸1弹逐渐变小和模糊

 

  图4  炸1弹爆炸的效果
 

  本例的实现代码如下:
 

view plaincopy to clipboardprint?
package net.blogjava.mobile;  
 
  import android.app.Activity;  
  import android.graphics.drawable.AnimationDrawable;  
  import android.media.MediaPlayer;  
  import android.os.Bundle;  
  import android.view.MotionEvent;  
  import android.view.View;  
  import android.view.View.OnTouchListener;  
  import android.view.animation.Animation;  
  import android.view.animation.AnimationUtils;  
  import android.view.animation.Animation.AnimationListener;  
  import android.widget.ImageView;  
 
  public class Main extends Activity implements OnTouchListener,AnimationListener  
  {  
  private ImageView ivMissile;  
  private MyImageView ivBlast;  
  private AnimationDrawable animationDrawable;  
  private Animation missileAnimation;  
  @Override 
  public boolean onTouch(View view, MotionEvent event)  
  {  
  //  触摸炸1弹后,开始播放动画  
  ivMissile.startAnimation(missileAnimation);  
  return false;  
  }  
  @Override 
  public void onAnimationEnd(Animation animation)  
  {  
  //  在播放投掷炸1弹动画结束后,显示MyImageView组件,并将显示炸1弹的ImageView组件隐藏  
  ivBlast.setVisibility(View.VISIBLE);  
  ivMissile.setVisibility(View.INVISIBLE);  
  try 
  {  
  //  开始播放爆炸的声音  
  MediaPlayer mediaPlayer = MediaPlayer.create(this, R.raw.bomb);  
  mediaPlayer.stop();  
  mediaPlayer.prepare();  
  mediaPlayer.start();  
  }  
  catch (Exception e)  
  {          
  }  
  animationDrawable.stop();  
  //  播放爆炸效果动画  
  animationDrawable.start();  
  }  
  @Override 
  public void onAnimationRepeat(Animation animation)  
  {  
  }  
  @Override 
  public void onAnimationStart(Animation animation)  
  {  
  }  
  @Override 
  public void onCreate(Bundle savedInstanceState)  
  {  
  super.onCreate(savedInstanceState);  
  setContentView(R.layout.main);  
  ivMissile = (ImageView) findViewById(R.id.ivMissile);  
  ivMissile.setOnTouchListener(this);  
  ivBlast = (MyImageView) findViewById(R.id.ivBlast);  
  ivBlast.setBackgroundResource(R.anim.blast);  
  Object backgroundObject = ivBlast.getBackground();  
  animationDrawable = (AnimationDrawable) backgroundObject;  
  ivBlast.animationDrawable = animationDrawable;  
  missileAnimation = AnimationUtils.loadAnimation(this, R.anim.missile);  
  missileAnimation.setAnimationListener(this);  
  //  在程序启动后,将显示爆炸效果的MyImageView组件隐藏  
  ivBlast.setVisibility(View.INVISIBLE);  
  ivBlast.ivMissile = ivMissile;  
  }  
  } 

package net.blogjava.mobile;   import android.app.Activity;   import android.graphics.drawable.AnimationDrawable;   import android.media.MediaPlayer;   import android.os.Bundle;   import android.view.MotionEvent;   import android.view.View;   import android.view.View.OnTouchListener;   import android.view.animation.Animation;   import android.view.animation.AnimationUtils;   import android.view.animation.Animation.AnimationListener;   import android.widget.ImageView;   public class Main extends Activity implements OnTouchListener,AnimationListener   {   private ImageView ivMissile;   private MyImageView ivBlast;   private AnimationDrawable animationDrawable;   private Animation missileAnimation;   @Override   public boolean onTouch(View view, MotionEvent event)   {   // 触摸炸1弹后,开始播放动画   ivMissile.startAnimation(missileAnimation);   return false;   }   @Override   public void onAnimationEnd(Animation animation)   {   // 在播放投掷炸1弹动画结束后,显示MyImageView组件,并将显示炸1弹的ImageView组件隐藏   ivBlast.setVisibility(View.VISIBLE);   ivMissile.setVisibility(View.INVISIBLE);   try   {   // 开始播放爆炸的声音   MediaPlayer mediaPlayer = MediaPlayer.create(this, R.raw.bomb);   mediaPlayer.stop();   mediaPlayer.prepare();   mediaPlayer.start();   }   catch (Exception e)   {   }   animationDrawable.stop();   // 播放爆炸效果动画   animationDrawable.start();   }   @Override   public void onAnimationRepeat(Animation animation)   {   }   @Override   public void onAnimationStart(Animation animation)   {   }   @Override   public void onCreate(Bundle savedInstanceState)   {   super.onCreate(savedInstanceState);   setContentView(R.layout.main);   ivMissile = (ImageView) findViewById(R.id.ivMissile);   ivMissile.setOnTouchListener(this);   ivBlast = (MyImageView) findViewById(R.id.ivBlast);   ivBlast.setBackgroundResource(R.anim.blast);   Object backgroundObject = ivBlast.getBackground();   animationDrawable = (AnimationDrawable) backgroundObject;   ivBlast.animationDrawable = animationDrawable;   missileAnimation = AnimationUtils.loadAnimation(this, R.anim.missile);   missileAnimation.setAnimationListener(this);   // 在程序启动后,将显示爆炸效果的MyImageView组件隐藏   ivBlast.setVisibility(View.INVISIBLE);   ivBlast.ivMissile = ivMissile;   }   }
  总结
  本文主要介绍了旋转补间动画和透明度补间动画。通过将四种补间动画结合使用,可以实现非常有趣的动画效果。
 

  作者介绍
  李宁,东北大学计算机专业硕士,拥有超过10年的软件开发经验。曾任国内某知名企业项目经理;目前担任eoeandroid和ophonesdn版主;中国移动开发者社区OPhone专家;51CTO客作专家;CSDN博客专家。曾领导并参与开发了多个大中型项目。目前主要从事Android及其相关产品的研发。从2005年进入写作领域以来,为《程序员》、《电脑编程技巧与维护》、《电脑报》、IT168、天极网等平面媒体和网络媒体撰写了一百多篇原创技术和评论文章。并在个人blog(http://nokiaguy.blogjava.net)上发表了大量的原创技术文章。2007年获《电脑编程技巧与维护》优秀作者。2009年获得OPhone征文大赛二等奖。个人著作:《Android/OPhone开发完全讲义》、《人人都玩开心网:Ext JS+Android+SSH整合开发Web与移动SNS》、《Java Web开发速学宝典》。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值