逐帧动画详解
2016-08-30 20:36
351 查看
概述
逐帧动画(Frame Animation),是通过将一系列图片按照一定的顺序展示实现的动画。同是视图动画(View Animation),在使用时比补间动画(Tween animation)要简单很多。
一、逐帧动画的使用
(1).使用xml文件创建
节点介绍:
<animation-list>:必须作为根元素,可以包含一个或多个<item>元素。
<item>:代表一帧动画。
属性介绍:
android:oneshot:若等于true,动画只执行一次;否则一直循环。
android:drawable:当前帧所对应的图片资源。
android:duration:当前帧持续的时长,单位毫秒。
示例代码:
/res/drawable目录下添加如下5张图片。
![](http://img.blog.csdn.net/20160830203748523?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
在/res/drawable目录下添加wifi_anim.xml文件。
(2).使用java代码创建
示例代码:
注意:在Activity的onCreate()方法中,由于Window对象还未初始化完成,此时调用animation.start(),动画不会执行。若需要在Activity启动时就显示动画,可以在onWindowFocusChanged(boolean hasFocus)方法中启动。
二、逐帧动画的分析
逐帧动画是通过AnimationDrawable类来实现。在AnimationDrawable类中,定义了一个AnimationState类型的成员变量mAnimationState,用来存储一系列的drawable对象。
AnimationState继承自DrawableContainerState类。AnimationState类自己定义了成员变量mDurations和mOneShot,分别存储每一帧的时长和动画是否需要循环。而在其父类中有一个Drawable类型数组mDrawables,用于存储每一帧drawable对象。
当调用addFrame()方法时,动画的每一帧被依次添加到成员变量mAnimationState中。
最后,调用start()方法启动动画。方法内部调用了setFrame()方法,在setFrame()中调用selectDrawable(),传入当前帧的索引,并在方法最后调用invalidateSelf()重写绘制。
逐帧动画(Frame Animation),是通过将一系列图片按照一定的顺序展示实现的动画。同是视图动画(View Animation),在使用时比补间动画(Tween animation)要简单很多。
一、逐帧动画的使用
(1).使用xml文件创建
节点介绍:
<animation-list>:必须作为根元素,可以包含一个或多个<item>元素。
<item>:代表一帧动画。
属性介绍:
android:oneshot:若等于true,动画只执行一次;否则一直循环。
android:drawable:当前帧所对应的图片资源。
android:duration:当前帧持续的时长,单位毫秒。
示例代码:
/res/drawable目录下添加如下5张图片。
在/res/drawable目录下添加wifi_anim.xml文件。
<?xml version="1.0" encoding="utf-8"?> <animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false"> <item android:drawable="@drawable/card_icon_wifi_0" android:duration="500" /> <item android:drawable="@drawable/card_icon_wifi_1" android:duration="500" /> <item android:drawable="@drawable/card_icon_wifi_2" android:duration="500" /> <item android:drawable="@drawable/card_icon_wifi_3" android:duration="500" /> <item android:drawable="@drawable/card_icon_wifi_4" android:duration="500" /> </animation-list>将上面创建的动画应用到布局的View中。
<ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/wifi_anim"/>在java代码中启动动画。
// 获取AnimationDrawable对象 AnimationDrawable animation = (AnimationDrawable) imageView.getBackground(); // 启动动画 animation.start();
(2).使用java代码创建
示例代码:
AnimationDrawable animation = new AnimationDrawable(); for (int i = 0; i < 5; i++) { int id = getResources().getIdentifier("card_icon_wifi_" + i, "drawable", getPackageName()); Drawable drawable = getResources().getDrawable(id); // 调用addFrame()方法依次添加drawable对象 animation.addFrame(drawable, 500); } // 添加到View中 imageView.setBackgroundDrawable(anim); // 启动动画 animation.start();
注意:在Activity的onCreate()方法中,由于Window对象还未初始化完成,此时调用animation.start(),动画不会执行。若需要在Activity启动时就显示动画,可以在onWindowFocusChanged(boolean hasFocus)方法中启动。
二、逐帧动画的分析
逐帧动画是通过AnimationDrawable类来实现。在AnimationDrawable类中,定义了一个AnimationState类型的成员变量mAnimationState,用来存储一系列的drawable对象。
public class AnimationDrawable extends DrawableContainer implements Runnable, Animatable { // ... private AnimationState mAnimationState; // ... }
AnimationState继承自DrawableContainerState类。AnimationState类自己定义了成员变量mDurations和mOneShot,分别存储每一帧的时长和动画是否需要循环。而在其父类中有一个Drawable类型数组mDrawables,用于存储每一帧drawable对象。
private final static class AnimationState extends DrawableContainerState { // ... private int[] mDurations; private boolean mOneShot = false; // ... public void addFrame(Drawable dr, int dur) { // ... int pos = super.addChild(dr); mDurations[pos] = dur; // ... } // ... } public abstract static class DrawableContainerState extends ConstantState { // ... Drawable[] mDrawables; // ... public final int addChild(Drawable dr) { // ... mDrawables[pos] = dr; // ... } }
当调用addFrame()方法时,动画的每一帧被依次添加到成员变量mAnimationState中。
public void addFrame(@NonNull Drawable frame, int duration) { mAnimationState.addFrame(frame, duration); if (!mRunning) { setFrame(0, true, false); } }
最后,调用start()方法启动动画。方法内部调用了setFrame()方法,在setFrame()中调用selectDrawable(),传入当前帧的索引,并在方法最后调用invalidateSelf()重写绘制。
public void start() { mAnimating = true; if (!isRunning()) { // Start from 0th frame. setFrame(0, false, mAnimationState.getChildCount() > 1 || !mAnimationState.mOneShot); } } private void setFrame(int frame, boolean unschedule, boolean animate) { if (frame >= mAnimationState.getChildCount()) { return; } mAnimating = animate; mCurFrame = frame; selectDrawable(frame); if (unschedule || animate) { unscheduleSelf(this); } if (animate) { // Unscheduling may have clobbered these values; restore them mCurFrame = frame; mRunning = true; scheduleSelf(this, SystemClock.uptimeMillis() + mAnimationState.mDurations[frame]); } }
相关文章推荐
- Android动画之逐帧动画(Frame Animation)实例详解
- Android中的动画实现详解(2)--逐帧动画
- Android中的动画详解系列【1】——逐帧动画
- Android动画之逐帧动画(Frame Animation)实例详解
- Android动画之逐帧动画(Frame Animation)实例详解
- Android 逐帧动画创建实例详解
- Android中的动画详解系列【1】——逐帧动画
- 逐帧动画详解一
- Android动画详解(一) 逐帧动画
- Android中的动画详解系列【1】——逐帧动画
- Android动画之逐帧动画(Frame Animation)实例详解
- Android--Animotion动画详解-逐帧动画,补间动画,属性动画。
- Android动画之逐帧动画(FrameAnimation)详解
- Android动画之逐帧动画(FrameAnimation)详解
- Windows下Ping命令详解及使用小技巧
- JavaScript封装的常用工具类库bee.js用法详解【经典类库】
- 基于Java字符编码的使用详解
- Java使用AES加密和解密的实例详解
- 将15位身份证补全为18位身份证的算法示例详解