• Android--逐帧动画FrameAnimation


    前言

      开门见山,本篇博客讲解一下如何在Android平台下播放一个逐帧动画。逐帧动画在Android下可以通过代码和XML文件两种方式定义,本篇博客都将讲到,最后将以一个简单的Demo来演示两种方式定义的逐帧动画的播放。

      本篇博客的主要内容:

    1. Android中的逐帧动画
    2. 使用XML定义的资源文件设置动画帧
    3. 使用Java代码创建逐帧动画

    Android中的逐帧动画

      先来说说什么是逐帧动画,逐帧动画是一种常见的动画形式(Frame By Frame),其原理是在“连续的关键帧”中分解动画动作,也就是在时间轴的每帧上逐帧绘制不同的内容,使其连续播放而成动画。 因为逐帧动画的帧序列内容不一样,不但给制作增加了负担而且最终输出的文件量也很大,但它的优势也很明显:逐帧动画具有非常大的灵活性,几乎可以表现任何想表现的内容,而它类似与电影的播放模式,很适合于表演细腻的动画。

      在Android中逐帧动画需要得到AnimationDrawable类的支持,它位于"android.graphics.drawable.AnimationDrawable"包下,是Drawable的间接子类。它主要用来创建一个逐帧动画,并且可以对帧进行拉伸,把它设置为View的背景即可使用AnimationDrawable.start()方法播放。既然逐帧动画是需要播放一帧一帧的图像,所以需要为其添加帧。在Android中提供了两种方式为AnimationDrawable添加帧:XML定义的资源文件和Java代码创建,后面再详细讲讲这两种添加帧的方式。

      光为AnimationDrawable设置帧还不能完成播放动画的功能,还需要AnimationDrawable定义好的其他的一些方法来操作逐帧动画,下面简单介绍一下AnimationDrawable的常用方法:

    • void start():开始播放逐帧动画。
    • void stop():停止播放逐帧动画。
    • void addFrame(Drawable frame,int duration):为AnimationDrawable添加一帧,并设置持续时间。
    • int getDuration(int i):得到指定index的帧的持续时间。
    • Drawable getFrame(int index):得到指定index的帧Drawable。
    • int getNumberOfFrames():得到当前AnimationDrawable的所有帧数量。
    • boolean isOneShot():当前AnimationDrawable是否执行一次,返回true执行一次,false循环播放。
    • boolean isRunning():当前AnimationDrawable是否正在播放。
    • void setOneShot(boolean oneShot):设置AnimationDrawable是否执行一次,true执行一次,false循环播放

    使用XML定义的资源文件设置动画帧

      Android下所有的资源文件均要放在/res目录下,对于动画帧的资源需要当成一个Drawable,所以需要把它放在/res/Drawable目录下。而定义逐帧动画非常简单,只要在<animation-list.../>元素中使用<item.../>子元素定义动画的全部帧,并制定各帧的持续时间即可。还可以在<animation-list.../>元素中添加属性,来设定逐帧动画的属性。

      例如:

    1 <?xml version="1.0" encoding="utf-8"?>
    2 <animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false"  >
    3     <!-- 定义一个动画帧,Drawable为img0,持续时间50毫秒 -->
    4     <item android:drawable="@drawable/img0" android:duration="50" />
    5 </animation-list>

      定义好逐帧动画的资源文件之后,只需要使用getResources().getDrawable(int)方法获取AnimationDrawable示例,然后把它设置为某个View的背景即可。

      下面通过一个简单的Demo,来演示如何播放一个XML定义的逐帧动画,布局很简单,一个ImageView来承载逐帧动画,两个Button控制播放与停止:

      XML帧动画的资源文件:

     1 <?xml version="1.0" encoding="utf-8"?>
     2 <animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false"  >
     3     <!-- 定义一个动画帧,Drawable为img0,持续时间50毫秒 -->
     4     <item android:drawable="@drawable/img0" android:duration="50" />
     5 <item android:drawable="@drawable/img1" android:duration="50" />
     6 <item android:drawable="@drawable/img2" android:duration="50" />
     7 <item android:drawable="@drawable/img3" android:duration="50" />
     8 <item android:drawable="@drawable/img4" android:duration="50" />
     9 <item android:drawable="@drawable/img5" android:duration="50" />
    10 <item android:drawable="@drawable/img6" android:duration="50" />
    11 <item android:drawable="@drawable/img7" android:duration="50" />
    12 <item android:drawable="@drawable/img8" android:duration="50" />
    13 <item android:drawable="@drawable/img9" android:duration="50" />
    14 <item android:drawable="@drawable/img10" android:duration="50" />
    15 <item android:drawable="@drawable/img11" android:duration="50" />
    16 <item android:drawable="@drawable/img12" android:duration="50" />
    17 <item android:drawable="@drawable/img13" android:duration="50" />
    18 <item android:drawable="@drawable/img14" android:duration="50" />
    19 <item android:drawable="@drawable/img15" android:duration="50" />
    20 <item android:drawable="@drawable/img16" android:duration="50" />
    21 <item android:drawable="@drawable/img17" android:duration="50" />
    22 <item android:drawable="@drawable/img18" android:duration="50" />
    23 <item android:drawable="@drawable/img19" android:duration="50" />
    24 <item android:drawable="@drawable/img20" android:duration="50" />
    25 <item android:drawable="@drawable/img21" android:duration="50" />
    26 <item android:drawable="@drawable/img22" android:duration="50" />
    27 <item android:drawable="@drawable/img23" android:duration="50" />
    28 <item android:drawable="@drawable/img24" android:duration="50" />
    29 </animation-list>
    View Code

      实现代码:

     1 package cn.bgxt.frameanimationdemo;
     2 
     3 import android.app.Activity;
     4 import android.graphics.drawable.AnimationDrawable;
     5 import android.os.Bundle;
     6 import android.util.Log;
     7 import android.view.View;
     8 import android.view.View.OnClickListener;
     9 import android.widget.Button;
    10 import android.widget.ImageView;
    11 import android.widget.Toast;
    12 
    13 public class ToXMLActivity extends Activity {
    14 
    15     private Button btn_start, btn_stop;
    16     private ImageView iv_frame;
    17     private AnimationDrawable frameAnim;
    18 
    19     @Override
    20     protected void onCreate(Bundle savedInstanceState) {
    21         super.onCreate(savedInstanceState);
    22         setContentView(R.layout.activity_frameanim);
    23 
    24         btn_start = (Button) findViewById(R.id.btn_start);
    25         btn_stop = (Button) findViewById(R.id.btn_stop);
    26 
    27         btn_start.setOnClickListener(click);
    28         btn_stop.setOnClickListener(click);
    29 
    30         iv_frame = (ImageView) findViewById(R.id.iv_frame);
    31         
    32         // 通过逐帧动画的资源文件获得AnimationDrawable示例
    33         frameAnim=(AnimationDrawable) getResources().getDrawable(R.drawable.bullet_anim);
    34         // 把AnimationDrawable设置为ImageView的背景
    35         iv_frame.setBackgroundDrawable(frameAnim);
    36     }
    37 
    38     private View.OnClickListener click = new OnClickListener() {
    39 
    40         @Override
    41         public void onClick(View v) {
    42             switch (v.getId()) {
    43             case R.id.btn_start:
    44                 start();
    45                 break;
    46             case R.id.btn_stop:
    47                 stop();
    48                 break;
    49             default:
    50                 break;
    51             }
    52         }
    53     };
    54 
    55     /**
    56      * 开始播放
    57      */
    58     protected void start() {
    59         if (frameAnim != null && !frameAnim.isRunning()) {
    60             frameAnim.start();
    61             Toast.makeText(ToXMLActivity.this, "开始播放", 0).show();
    62             Log.i("main", "index 为5的帧持续时间为:"+frameAnim.getDuration(5)+"毫秒");
    63             Log.i("main", "当前AnimationDrawable一共有"+frameAnim.getNumberOfFrames()+"帧");
    64         }
    65     }
    66 
    67     /**
    68      * 停止播放
    69      */
    70     protected void stop() {
    71         if (frameAnim != null && frameAnim.isRunning()) {
    72             frameAnim.stop();
    73             Toast.makeText(ToXMLActivity.this, "停止播放", 0).show();
    74         }
    75     }
    76 }

    使用Java代码创建逐帧动画

      在Android中,除了可以通过XML文件定义一个逐帧动画之外,还可以通过AnimationDrawable.addFrame()方法为AnimationDrawable添加动画帧,上面已经提供了addFrame()的方法签名,它可以设置添加动画帧的Drawable和持续时间。其实没什么技术含量,下面通过一个简单的Demo演示一下。

      实现代码:

      1 package cn.bgxt.frameanimationdemo;
      2 
      3 import android.app.Activity;
      4 import android.graphics.BitmapFactory;
      5 import android.graphics.Canvas;
      6 import android.graphics.ColorFilter;
      7 import android.graphics.drawable.AnimationDrawable;
      8 import android.graphics.drawable.BitmapDrawable;
      9 import android.graphics.drawable.Drawable;
     10 import android.os.Bundle;
     11 import android.view.View;
     12 import android.view.View.OnClickListener;
     13 import android.widget.Button;
     14 import android.widget.ImageView;
     15 import android.widget.Toast;
     16 
     17 public class ToCodeActivity extends Activity {
     18     private Button btn_start, btn_stop;
     19     private ImageView iv_frame;
     20     private AnimationDrawable frameAnim;
     21 
     22     @Override
     23     protected void onCreate(Bundle savedInstanceState) {
     24         super.onCreate(savedInstanceState);
     25         setContentView(R.layout.activity_frameanim);
     26 
     27         btn_start = (Button) findViewById(R.id.btn_start);
     28         btn_stop = (Button) findViewById(R.id.btn_stop);
     29 
     30         btn_start.setOnClickListener(click);
     31         btn_stop.setOnClickListener(click);
     32 
     33         iv_frame = (ImageView) findViewById(R.id.iv_frame);
     34 
     35         frameAnim =new AnimationDrawable();
     36         // 为AnimationDrawable添加动画帧
     37         frameAnim.addFrame(getResources().getDrawable(R.drawable.img0), 50);
     38         frameAnim.addFrame(getResources().getDrawable(R.drawable.img1), 50);
     39         frameAnim.addFrame(getResources().getDrawable(R.drawable.img2), 50);
     40         frameAnim.addFrame(getResources().getDrawable(R.drawable.img3), 50);
     41         frameAnim.addFrame(getResources().getDrawable(R.drawable.img4), 50);
     42         frameAnim.addFrame(getResources().getDrawable(R.drawable.img5), 50);
     43         frameAnim.addFrame(getResources().getDrawable(R.drawable.img6), 50);
     44         frameAnim.addFrame(getResources().getDrawable(R.drawable.img7), 50);
     45         frameAnim.addFrame(getResources().getDrawable(R.drawable.img8), 50);
     46         frameAnim.addFrame(getResources().getDrawable(R.drawable.img9), 50);
     47         frameAnim.addFrame(getResources().getDrawable(R.drawable.img10), 50);
     48         frameAnim.addFrame(getResources().getDrawable(R.drawable.img11), 50);
     49         frameAnim.addFrame(getResources().getDrawable(R.drawable.img12), 50);
     50         frameAnim.addFrame(getResources().getDrawable(R.drawable.img13), 50);
     51         frameAnim.addFrame(getResources().getDrawable(R.drawable.img14), 50);
     52         frameAnim.addFrame(getResources().getDrawable(R.drawable.img15), 50);
     53         frameAnim.addFrame(getResources().getDrawable(R.drawable.img16), 50);
     54         frameAnim.addFrame(getResources().getDrawable(R.drawable.img17), 50);
     55         frameAnim.addFrame(getResources().getDrawable(R.drawable.img18), 50);
     56         frameAnim.addFrame(getResources().getDrawable(R.drawable.img19), 50);
     57         frameAnim.addFrame(getResources().getDrawable(R.drawable.img20), 50);
     58         frameAnim.addFrame(getResources().getDrawable(R.drawable.img21), 50);
     59         frameAnim.addFrame(getResources().getDrawable(R.drawable.img22), 50);
     60         frameAnim.addFrame(getResources().getDrawable(R.drawable.img23), 50);
     61         frameAnim.addFrame(getResources().getDrawable(R.drawable.img24), 50);
     62         frameAnim.setOneShot(false);
     63         
     64         // 设置ImageView的背景为AnimationDrawable
     65         iv_frame.setBackgroundDrawable(frameAnim);
     66     }
     67 
     68     private View.OnClickListener click = new OnClickListener() {
     69 
     70         @Override
     71         public void onClick(View v) {
     72             switch (v.getId()) {
     73             case R.id.btn_start:
     74                 start();
     75                 break;
     76             case R.id.btn_stop:
     77                 stop();
     78                 break;
     79             default:
     80                 break;
     81             }
     82 
     83         }
     84     };
     85 
     86     /**
     87      * 开始播放
     88      */
     89     protected void start() {
     90         if (frameAnim != null && !frameAnim.isRunning()) {
     91             frameAnim.start();
     92             Toast.makeText(ToCodeActivity.this, "开始播放", 0).show();
     93         }
     94     }
     95     /**
     96      * 停止播放
     97      */
     98     protected void stop() {
     99         if (frameAnim != null && frameAnim.isRunning()) {
    100             frameAnim.stop();
    101             Toast.makeText(ToCodeActivity.this, "停止播放", 0).show();
    102         }
    103     }
    104 
    105 }

      其实上面两个Demo实现的都是一种效果,是一个子弹击中墙体的逐帧动画效果,下面展示一下Demo的运行效果:

      源码下载

     

  • 相关阅读:
    快速排序算法
    HTTP中的重定向和请求转发的区别
    单链表的逆置(头插法和就地逆置)
    水仙花数学习
    构建n位元的格雷码
    算法学习day01 栈和队列
    数据结构学习总结 线性表之双向链表
    设计模式
    Nginx 初步认识
    数据结构学习总结(2) 线性表之单链表
  • 原文地址:https://www.cnblogs.com/plokmju/p/android_AnimationDrawable.html
Copyright © 2020-2023  润新知