Android--逐帧动画FrameAnimation

简介:

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帧动画的资源文件:

  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://www.cnblogs.com/plokmju/p/android_AnimationDrawable.html,如需转载请自行联系原作者


相关文章
|
6月前
|
Android开发 开发者
Android利用SVG实现动画效果
本文介绍了如何在Android中利用SVG实现动画效果。首先通过定义`pathData`参数(如M、L、Z等)绘制一个简单的三角形SVG图形,然后借助`objectAnimator`实现动态的线条绘制动画。文章详细讲解了从配置`build.gradle`支持VectorDrawable,到创建动画文件、关联SVG与动画,最后在Activity中启动动画的完整流程。此外,还提供了SVG绘制原理及工具推荐,帮助开发者更好地理解和应用SVG动画技术。
257 30
|
6月前
|
Android开发 UED 计算机视觉
Android自定义view之线条等待动画(灵感来源:金铲铲之战)
本文介绍了一款受游戏“金铲铲之战”启发的Android自定义View——线条等待动画的实现过程。通过将布局分为10份,利用`onSizeChanged`测量最小长度,并借助画笔绘制动态线条,实现渐变伸缩效果。动画逻辑通过四个变量控制线条的增长与回退,最终形成流畅的等待动画。代码中详细展示了画笔初始化、线条绘制及动画更新的核心步骤,并提供完整源码供参考。此动画适用于加载场景,提升用户体验。
495 5
Android自定义view之线条等待动画(灵感来源:金铲铲之战)
|
6月前
|
API Android开发 开发者
Android颜色渐变动画效果的实现
本文介绍了在Android中实现颜色渐变动画效果的方法,重点讲解了插值器(TypeEvaluator)的使用与自定义。通过Android自带的颜色插值器ArgbEvaluator,可以轻松实现背景色的渐变动画。文章详细分析了ArgbEvaluator的核心代码,并演示了如何利用Color.colorToHSV和Color.HSVToColor方法自定义颜色插值器MyColorEvaluator。最后提供了完整的源码示例,包括ColorGradient视图类和MyColorEvaluator类,帮助开发者更好地理解和应用颜色渐变动画技术。
179 3
|
6月前
|
Android开发 开发者
Android SVG动画详细例子
本文详细讲解了在Android中利用SVG实现动画效果的方法,通过具体例子帮助开发者更好地理解和应用SVG动画。文章首先展示了动画的实现效果,接着回顾了之前的文章链接及常见问题(如属性名大小写错误)。核心内容包括:1) 使用阿里图库获取SVG图形;2) 借助工具将SVG转换为VectorDrawable;3) 为每个路径添加动画绑定属性;4) 创建动画文件并关联SVG;5) 在ImageView中引用动画文件;6) 在Activity中启动动画。文末还提供了完整的代码示例和源码下载链接,方便读者实践操作。
311 65
|
6月前
|
XML Java Maven
Android线条等待动画JMWorkProgress(可添加依赖直接使用)
这是一篇关于Android线条等待动画JMWorkProgress的教程文章,作者计蒙将其代码开源至GitHub,提升可读性。文章介绍了如何通过添加依赖库使用该动画,并详细讲解了XML与Java中的配置方法,包括改变线条颜色、宽度、添加文字等自定义属性。项目已支持直接依赖集成(`implementation &#39;com.github.Yufseven:JMWorkProgress:v1.0&#39;`),开发者可以快速上手实现炫酷的等待动画效果。文末附有GitHub项目地址,欢迎访问并点赞支持!
165 26
|
6月前
|
XML Android开发 数据格式
Android中SlidingDrawer利用透明动画提示效果
本文介绍了在Android中使用`SlidingDrawer`实现带有透明动画提示效果的方法。通过XML布局配置`SlidingDrawer`的把手(handle)和内容(content),结合Activity中的代码实现动态动画效果。最终实现了交互性强、视觉效果良好的滑动抽屉功能。
Android中SlidingDrawer利用透明动画提示效果
|
6月前
|
XML Java Android开发
Android 动画之帧动画 + 补间动画 + 属性动画
本文介绍了Android开发中的三种动画类型:帧动画、补间动画和属性动画。帧动画通过依次播放一系列静态图片实现动态效果,支持Java代码与XML两种实现方式。补间动画基于起始和结束位置自动生成过渡效果,涵盖透明度、位移、旋转、缩放及组合动画等多种形式,并可搭配插值器优化动画过程。属性动画则通过改变对象属性实现动画,支持透明度、位移、旋转、缩放及组合动画,灵活性更高且适用于更复杂的场景。文中提供了详细的代码示例,帮助开发者快速上手。
325 15
|
6月前
|
Android开发 开发者
Android自定义view之围棋动画(化繁为简)
本文介绍了Android自定义View的动画实现,通过两个案例拓展动态效果。第一个案例基于`drawArc`方法实现单次动画,借助布尔值控制动画流程。第二个案例以围棋动画为例,从简单的小球直线运动到双向变速运动,最终实现循环动画效果。代码结构清晰,逻辑简明,展示了如何化繁为简实现复杂动画,帮助读者拓展动态效果设计思路。文末提供完整源码,适合初学者和进阶开发者学习参考。
106 0
Android自定义view之围棋动画(化繁为简)
|
6月前
|
Java Android开发 开发者
Android自定义view之围棋动画
本文详细介绍了在Android中自定义View实现围棋动画的过程。从测量宽高、绘制棋盘背景,到创建固定棋子及动态棋子,最后通过属性动画实现棋子的移动效果。文章还讲解了如何通过自定义属性调整棋子和棋盘的颜色及动画时长,并优化视觉效果,如添加渐变色让白子更明显。最终效果既可作为围棋动画展示,也可用作加载等待动画。代码完整,适合进阶开发者学习参考。
128 0

热门文章

最新文章