一、概述
本节主要介绍下逐帧动画的基本使用,下面我们就从XML方式创建动画和代码方式创建动画来分别说下吧
二、逐帧动画介绍
在开始介绍逐帧动画之前,先来看一下在本例中我们要实现的逐帧动画的效果
逐帧动画,我的理解就是将一帧帧的静态图片进行有序的展示,利用人眼的视觉暂留现象来呈现给用户一种连贯的动画效果。在实际编写代码过程中,我们主要是通过系统提供的AnimationDrawable类来控制逐帧动画,AnimationDrawable又是何许类也?这是API中给我们的介绍
通过API介绍我们知道,AnimationDrawable类一种用于创建逐帧动画的对象,由一系列可绘制对象定义,该对象可以用作视图对象的背景。创建逐帧动画最简单的方法是在XML文件中定义动画,下面来让我们看下具体的实现吧。
三、 通过xml定义动画
将我们所需要的图片放入mipmap文件夹下,当前动画即由这6帧组成
在drawable文件夹下,新建一个anim_frame_load.xml文件,现在Android Studio只支持将animation-list的xml文件放在drawable目录之下
//res右键=>Android Resource File
=>File name:anim_frame_load(xml文件名字),Resource type:Drawable,Root element:animation-list,Directory name:drawable(文件夹的名字)
drawable目录结构如下所示
在anim_frame_load.xml文件中编写animation-list,并可以设置属性android:id="selected"和设置是否只播放一次android:oneshot=“false”
<animation-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@mipmap/load01" android:duration="200"></item>
<item android:drawable="@mipmap/load02" android:duration="200"></item>
<item android:drawable="@mipmap/load03" android:duration="200"></item>
<item android:drawable="@mipmap/load04" android:duration="200"></item>
<item android:drawable="@mipmap/load05" android:duration="200"></item>
<item android:drawable="@mipmap/load06" android:duration="200"></item>
</animation-list>
这是我们的帧动画类,通过AnimationDrawable来执行动画,代码比较简单
public class FrameAnimationTest extends Activity{
//动画对象
AnimationDrawable animDrawable;
//添加动画的控件
ImageView imgLoad;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.anim_frame_load);
initView();
addClickListener();
}
private void initView() {
imgLoad = (ImageView) findViewById(R.id.img_load);
}
private void addClickListener() {
findViewById(R.id.tv_load_start).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//开始逐帧动画
startAnimByXml();
}
});
findViewById(R.id.tv_load_stop).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//结束动画
stopAnim();
}
});
}
/** xml方式开始动画*/
private void startAnimByXml() {
imgLoad.setBackgroundResource(R.drawable.anim_frame_load);
animDrawable = (AnimationDrawable) imgLoad.getBackground();
//如果动画正在运行,则此方法没有效果,内部已经判断了,所以我们不必判断动画状态了
animDrawable.start();
}
/** 结束动画*/
private void stopAnim() {
if(animDrawable != null){
//如果动画不运行,此方法没有效果,内部已经判断了,所以我们不必判断动画状态了
animDrawable.stop();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if(animDrawable != null){
//当界面销毁的时候,销毁animDrawable
animDrawable = null;
}
}
}
其实帧动画不仅可以通过xml方式定义,还能在代码中直接实现,因为AnimationDrawable类为我们提供了addFrame(Drawable frame, int duration) 这个直接添加帧图片Drawable对象到动画中的方法,同时它还提供了一系列设置动画属性和获取状态的公开方法,下面来让我们看看具体的实现。
四、 直接在代码中实现
将图片添加到项目mipmap目录下
我们直接在代码中通过AnimationDrawable来实现帧动画,所以就不必编写xml文件了,这种方式比较适用于你的项目动画需要动态扩展或者项目对于动画的灵活性有很高的要求,而如果你更加看重的是动画的高度复用性,那么就优先选择xml定义动画的方式吧,毕竟这也是API所推荐的方式。
public class FrameAnimationTest extends Activity{
//当使用java code实现的时,动画图片资源数组
int[] anims = {R.mipmap.load01
, R.mipmap.load02
, R.mipmap.load03
, R.mipmap.load04
, R.mipmap.load05
, R.mipmap.load06};
//动画对象
AnimationDrawable animDrawable;
//添加动画的控件
ImageView imgLoad;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.anim_frame_load);
initView();
addClickListener();
}
private void initView() {
imgLoad = (ImageView) findViewById(R.id.img_load);
}
private void addClickListener() {
//开始逐帧动画
findViewById(R.id.tv_load_start).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
statrAnimByJavaCode();
}
});
//结束动画
findViewById(R.id.tv_load_stop).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
stopAnim();
}
});
}
/** java code方式开始动画*/
private void statrAnimByJavaCode() {
if(animDrawable == null){
animDrawable = new AnimationDrawable();
}
for(int source : anims) {
//添加每帧图片资源和设置每帧持续时间
animDrawable.addFrame(getResources().getDrawable(source), 200);
}
animDrawable.setOneShot(false);//循环播放
imgLoad.setBackground(animDrawable);
animDrawable.start();
}
/** 结束动画*/
private void stopAnim() {
if(animDrawable != null){
animDrawable.stop();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if(animDrawable != null){
animDrawable = null;
}
}
}
由于我们将AnimationDrawable对象的创建和动画的启动,都放在了点击监听方法onClick里,所以目前开始动画之前,界面是空白的,不会显示动画的第一帧图片,如果你有这方面的需求,解决的最快方法就是直接在layout文件里给view直接加上background
<!--这是我们要添加动画的View-->
<ImageView
android:id="@+id/img_load"
android:layout_width="68dp"
android:layout_height="68dp"
android:layout_centerInParent="true"
android:background="@drawable/anim_frame_load"
/>
五、 总结
好了,到这里帧动画的基本使用我们心里应该都有底了,但是对于源码层次的原理剖析,或者帧图片过大或者帧数量过多等具体情况的优化在这里都没有涉及,如果你想好好研究动画,那么就去一点点的深入吧。如果想要查看更多动画的基础知识,去我的博客目录里查看吧,因为关于每块知识点的介绍,博客单节写的比较零散,不容易查找。