前言

  开门见山,本篇博客讲解一下如何在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.../>元素中添加属性,来设定逐帧动画的属性。

  例如:

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

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

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

  XML帧动画的资源文件:

 <?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false" >
<!-- 定义一个动画帧,Drawable为img0,持续时间50毫秒 -->
<item android:drawable="@drawable/img0" android:duration="50" />
<item android:drawable="@drawable/img1" android:duration="50" />
<item android:drawable="@drawable/img2" android:duration="50" />
<item android:drawable="@drawable/img3" android:duration="50" />
<item android:drawable="@drawable/img4" android:duration="50" />
<item android:drawable="@drawable/img5" android:duration="50" />
<item android:drawable="@drawable/img6" android:duration="50" />
<item android:drawable="@drawable/img7" android:duration="50" />
<item android:drawable="@drawable/img8" android:duration="50" />
<item android:drawable="@drawable/img9" android:duration="50" />
<item android:drawable="@drawable/img10" android:duration="50" />
<item android:drawable="@drawable/img11" android:duration="50" />
<item android:drawable="@drawable/img12" android:duration="50" />
<item android:drawable="@drawable/img13" android:duration="50" />
<item android:drawable="@drawable/img14" android:duration="50" />
<item android:drawable="@drawable/img15" android:duration="50" />
<item android:drawable="@drawable/img16" android:duration="50" />
<item android:drawable="@drawable/img17" android:duration="50" />
<item android:drawable="@drawable/img18" android:duration="50" />
<item android:drawable="@drawable/img19" android:duration="50" />
<item android:drawable="@drawable/img20" android:duration="50" />
<item android:drawable="@drawable/img21" android:duration="50" />
<item android:drawable="@drawable/img22" android:duration="50" />
<item android:drawable="@drawable/img23" android:duration="50" />
<item android:drawable="@drawable/img24" android:duration="50" />
</animation-list>

  实现代码:

 package cn.bgxt.frameanimationdemo;

 import android.app.Activity;
import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast; public class ToXMLActivity extends Activity { private Button btn_start, btn_stop;
private ImageView iv_frame;
private AnimationDrawable frameAnim; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_frameanim); btn_start = (Button) findViewById(R.id.btn_start);
btn_stop = (Button) findViewById(R.id.btn_stop); btn_start.setOnClickListener(click);
btn_stop.setOnClickListener(click); iv_frame = (ImageView) findViewById(R.id.iv_frame); // 通过逐帧动画的资源文件获得AnimationDrawable示例
frameAnim=(AnimationDrawable) getResources().getDrawable(R.drawable.bullet_anim);
// 把AnimationDrawable设置为ImageView的背景
iv_frame.setBackgroundDrawable(frameAnim);
} private View.OnClickListener click = new OnClickListener() { @Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_start:
start();
break;
case R.id.btn_stop:
stop();
break;
default:
break;
}
}
}; /**
* 开始播放
*/
protected void start() {
if (frameAnim != null && !frameAnim.isRunning()) {
frameAnim.start();
Toast.makeText(ToXMLActivity.this, "开始播放", 0).show();
Log.i("main", "index 为5的帧持续时间为:"+frameAnim.getDuration(5)+"毫秒");
Log.i("main", "当前AnimationDrawable一共有"+frameAnim.getNumberOfFrames()+"帧");
}
} /**
* 停止播放
*/
protected void stop() {
if (frameAnim != null && frameAnim.isRunning()) {
frameAnim.stop();
Toast.makeText(ToXMLActivity.this, "停止播放", 0).show();
}
}
}

使用Java代码创建逐帧动画

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

  实现代码:

 package cn.bgxt.frameanimationdemo;

 import android.app.Activity;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast; public class ToCodeActivity extends Activity {
private Button btn_start, btn_stop;
private ImageView iv_frame;
private AnimationDrawable frameAnim; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_frameanim); btn_start = (Button) findViewById(R.id.btn_start);
btn_stop = (Button) findViewById(R.id.btn_stop); btn_start.setOnClickListener(click);
btn_stop.setOnClickListener(click); iv_frame = (ImageView) findViewById(R.id.iv_frame); frameAnim =new AnimationDrawable();
// 为AnimationDrawable添加动画帧
frameAnim.addFrame(getResources().getDrawable(R.drawable.img0), 50);
frameAnim.addFrame(getResources().getDrawable(R.drawable.img1), 50);
frameAnim.addFrame(getResources().getDrawable(R.drawable.img2), 50);
frameAnim.addFrame(getResources().getDrawable(R.drawable.img3), 50);
frameAnim.addFrame(getResources().getDrawable(R.drawable.img4), 50);
frameAnim.addFrame(getResources().getDrawable(R.drawable.img5), 50);
frameAnim.addFrame(getResources().getDrawable(R.drawable.img6), 50);
frameAnim.addFrame(getResources().getDrawable(R.drawable.img7), 50);
frameAnim.addFrame(getResources().getDrawable(R.drawable.img8), 50);
frameAnim.addFrame(getResources().getDrawable(R.drawable.img9), 50);
frameAnim.addFrame(getResources().getDrawable(R.drawable.img10), 50);
frameAnim.addFrame(getResources().getDrawable(R.drawable.img11), 50);
frameAnim.addFrame(getResources().getDrawable(R.drawable.img12), 50);
frameAnim.addFrame(getResources().getDrawable(R.drawable.img13), 50);
frameAnim.addFrame(getResources().getDrawable(R.drawable.img14), 50);
frameAnim.addFrame(getResources().getDrawable(R.drawable.img15), 50);
frameAnim.addFrame(getResources().getDrawable(R.drawable.img16), 50);
frameAnim.addFrame(getResources().getDrawable(R.drawable.img17), 50);
frameAnim.addFrame(getResources().getDrawable(R.drawable.img18), 50);
frameAnim.addFrame(getResources().getDrawable(R.drawable.img19), 50);
frameAnim.addFrame(getResources().getDrawable(R.drawable.img20), 50);
frameAnim.addFrame(getResources().getDrawable(R.drawable.img21), 50);
frameAnim.addFrame(getResources().getDrawable(R.drawable.img22), 50);
frameAnim.addFrame(getResources().getDrawable(R.drawable.img23), 50);
frameAnim.addFrame(getResources().getDrawable(R.drawable.img24), 50);
frameAnim.setOneShot(false); // 设置ImageView的背景为AnimationDrawable
iv_frame.setBackgroundDrawable(frameAnim);
} private View.OnClickListener click = new OnClickListener() { @Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_start:
start();
break;
case R.id.btn_stop:
stop();
break;
default:
break;
} }
}; /**
* 开始播放
*/
protected void start() {
if (frameAnim != null && !frameAnim.isRunning()) {
frameAnim.start();
Toast.makeText(ToCodeActivity.this, "开始播放", 0).show();
}
}
/**
* 停止播放
*/
protected void stop() {
if (frameAnim != null && frameAnim.isRunning()) {
frameAnim.stop();
Toast.makeText(ToCodeActivity.this, "停止播放", 0).show();
}
} }

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

  源码下载

Android--逐帧动画FrameAnimation的更多相关文章

  1. Android动画之逐帧动画(FrameAnimation)详解

    今天我们就来学习逐帧动画,废话少说直接上效果图如下: 帧动画的实现方式有两种: 一.在res/drawable文件夹下新建animation-list的XML实现帧动画 1.首先在res/drawab ...

  2. Android 逐帧动画isRunning 一直返回true的问题

    AnimationDrawabl主要通过xml实现逐帧动画,SDK实例如下: An AnimationDrawable defined in XML consists of a single < ...

  3. Android 逐帧动画

    原理: 逐帧动画是最简单的一种动画.原理就是把几张图片连续显示出来,以达到动画的效果.就相当于下面这种手绘翻页动画啦~ 实现: 1.需要建立一个animation-list来设置静态图片资源.持续时间 ...

  4. Android 逐帧动画( Drawable 动画),这一篇就够了

    前言 作为 Android 最常见的两种动画形式,逐帧动画( Drawable 动画),有着极其广泛的应用,它的原理与早起的电影以及 GIF 类似,就是把一张的图,按顺序快速切换,这样一来看上去就好像 ...

  5. Android 学习之逐帧动画(Frame)

    帧动画就是将一些列图片.依次播放. 利用肉眼的"视觉暂留"的原理,给用户的感觉是动画的错觉,逐帧动画的原理和早期的电影原理是一样的. a:须要定义逐帧动画,能够通过代码定义.也能够 ...

  6. Android动画效果之Frame Animation(逐帧动画)

    前言: 上一篇介绍了Android的Tween Animation(补间动画) Android动画效果之Tween Animation(补间动画),今天来总结下Android的另外一种动画Frame ...

  7. Android中的动画具体解释系列【1】——逐帧动画

    逐帧动画事实上非常easy,以下我们来看一个样例: <?xml version="1.0" encoding="utf-8"?> <anima ...

  8. Android简单逐帧动画Frame的实现(三)

    android之动画(三)通过AnimationDrawable控制逐帧动画     android与逐帧动画: 效果图: 当我们点击按钮时,该图片会不停的旋转,当再次点击按钮时,会停止在当前的状态. ...

  9. Android简单逐帧动画Frame的实现(二)

    Android简单逐帧动画Frame的实现   Android简单逐帧动画Frame的实现 1.逐帧动画 即是通过播放预先排序好的图片来实现动态的画面,感觉像是放电影. 2.实现步骤: 1. 在工程里 ...

  10. 转Android 用Animation-list实现逐帧动画

    Android 用Animation-list实现逐帧动画     第一步:先上图片素材,以下素材放到res/drawable目录下: http://blog.csdn.net/aminfo/arti ...

随机推荐

  1. HDU 2243考研路茫茫——单词情结 (AC自动机+矩阵快速幂)

    背单词,始终是复习英语的重要环节.在荒废了3年大学生涯后,Lele也终于要开始背单词了. 一天,Lele在某本单词书上看到了一个根据词根来背单词的方法.比如"ab",放在单词前一般 ...

  2. Python----爬虫入门系列等

    欢迎访问我的人生苦短系列(目前主要是Python爬虫入门) 传送门:https://www.jeson.xin/category/%E4%BA%BA%E7%94%9F%E8%8B%A6%E7%9F%A ...

  3. corel

    corel CorelDRAW X6 Corel CorelCAD 2017 32位/64位破解版

  4. Linux中安装MySQL

    因为使用yum安装.安装过程需保证网络通畅 一.安装mysql 1.yum安装mysqlCentOS7默认数据库是mariadb,配置等用着不习惯,因此决定改成mysql,但是CentOS7的yum源 ...

  5. Kubernetes1.7—DNS安装

    虽然通过了Service解决了Pod重建后IP动态变化(服务发现).负载均衡问题,但使用Service还是要需要知道CLUSTER-IP,而通过NDS可以解决该问题:在Kubernetes集群中可通过 ...

  6. Vue(三十三)国际化解决方案

    摘自:https://blog.csdn.net/qq_41485414/article/details/81093999 (1)第一种方式:中英文两套页面 优点:技术含量最低 缺点:占内存,响应慢, ...

  7. selenium python 设置窗口打开大小

    1. 窗口最大化 1 driver.maximize_window() 2. 设置窗口大小 1 driver.set_window_size(1920,1080) #分辨率1920 x 1080

  8. 二分- Count on Canton

    题目: 代码: 是一个蛇形数列,把题目上的那组数倒过来看成一个正三角形. 第一行有1个数,1-2行有三个数,1-4行有6个数,1-4行有10个数,1-5行有15个数..... 现在要求第n个数是多少, ...

  9. history.pushState()和history.replaceState()

    Html5 新增history对象的两个方法:history.pushState()和history.replaceState(),方法执行后,浏览器地址栏会变成你传的url,而页面并不会重新载入或跳 ...

  10. .NET Core 源码导航(按程序集链接)

    System.*.dll/dotnetfx mscorlib.dll/dotnetclr Microsoft.AspNetCore.dll Microsoft.EntityFrameworkCore. ...