一、逐帧动画介绍
逐帧动画是一种常见的动画形式(Frame By Frame),其原理是在“连续的关键帧”中分解动画动作,也就是在时间轴的每帧上逐帧绘制不同的内容,使其连续播放而成动画。 ——《百度百科》
逐帧动画是最好理解的动画,也是很简单暴力的动画。
二、实现
- 导入资源
如果你没有动画资源,可以将上面三张图片拖到Windows桌面,然后导入Android Studio中。
将这三张图片放置res/drawable-* 中(必须是drawable中,不能是mipmap,否则会找不到图片资源)。 - 然后“右键”drawable,创建一个animation-list的xml文件:
- 编写xml
<animation-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/frame_0" android:duration="100"/>
<item android:drawable="@drawable/frame_1" android:duration="100"/>
<item android:drawable="@drawable/frame_2" android:duration="100"/>
</animation-list>
在 <animation-list> 标签下仅有一种标签 <item> 可以使用,其标签仅有两个属性:
-drawable:就是对应的图片,
-duration :每一张图片显示的时间(单位ms)
- 加载这个animation-list,如果是对于ImageView,可以设置成他的src属性,如果是对于其他View或者ViewGroup,可以设置成background属性:
<ImageView
android:id="@+id/img_frame"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/anim_frame_one"/>
<TextView
android:id="@+id/tv_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="这是TextView"
android:gravity="center"
android:background="@drawable/anim_frame"/>
- 开始动画
在开始动画之前,我们要先拿到其所对应的Drawable,如上所示,对于ImageView,因为他是设置的src属性,所以可以通过img_frame.getDrawable()
来获取,而对于background属性,我们可以直接通过tv_text.getBackground()
来获取。
拿到之后,发现他们都是Drawable,并没有动画相关的方法!所以我们调试的时候看看这个Drawable是什么:
原来是AnimationDrawable,那么我们直接强行把获得的Drawable转换成AnimationDrawable,果然发现了有动画相关的方法:
btn_start_img.setOnClickListener {
(img_frame.drawable as AnimationDrawable).start()
}
btn_start_text.setOnClickListener {
(tv_text.background as AnimationDrawable).start()
}
接下来看看效果图:
三、AnimationDrawable
既然我们都知道了我们创建的animation-list文件会以Drawable的样子实现,那么我们完全可以动态创建Drawable的资源,然后赋值给ImageView的drawable属性或者其他View的background属性中。
动态加载动画
动态加载动画的话,就可以将我们在之前的布局中删除一行代码:
ImageView的
android:src="@drawable/anim_frame_one"
TextView的
android:background="@drawable/anim_frame"
val animDrawable = resources.getDrawable(R.drawable.anim_frame,null) as AnimationDrawable
val animDrawable2 = resources.getDrawable(R.drawable.anim_frame,null) as AnimationDrawable
btn_start_img.setOnClickListener {
img_frame.setImageDrawable(animDrawable)
(img_frame.drawable as AnimationDrawable).start()
}
btn_start_text.setOnClickListener {
//这里为什么要创建第二个animDrawable?
//如果还沿用第一个animDrawable,那么他们的引用会是
//同一个animDrawable,会出现其他错误。
tv_text.background = animDrawable2
(tv_text.background as AnimationDrawable).start()
}
AnimationDrawable的方法
- stop() -停止动画。
- isRunning():Boolean -判断动画是否正在运行。
- getNumberOfFrames():int -获取动画的帧数(该Demo用了3张图片,那么该方法返回的int为3)。
- getFrame(int index):Drawable -获取第index帧的图片。
- getDuration(int index):int -获取第index帧的显示时长。
- setOneShot(boolean oneShot) -设置是否播放一次动画。
- addFrame(Drawable frame, int duration) -添加一帧。
优缺点
优点
- 实现简单
缺点
- 图片占用资源大。
- 图片如果比较大,可能会OOM。
- 图片数量多的话,可能会造成卡顿。
- 只实现动画的播放,交互性很差。