Android逐帧动画了解及使用

简介

顾名思义,逐帧动画就是将一组图片资源一帧一帧播放,逐帧动画跟补间动画一样都可以通过XML或者Java代码实现。
当然不管哪种方式实现都离不开AnimationDrawable类的支持,我们来了解下这个类。

AnimationDrawable

首先看下它的属性定义:

 	<declare-styleable name="AnimationDrawable">
        <attr name="visible" />
        <attr name="variablePadding" />
        <!-- If true, the animation will only run a single time and then
             stop.  If false (the default), it will continually run,
             restarting at the first frame after the last has finished. -->
             //设置为true的话,动画就只会运行一次然后停止,设置为false的话就会接着从第一帧重新开始,默认是false
             //这个属性我们可以在xml中animation-list标签下设置或者在代码中通过setOneShot(boolean oneShot)方法设置
        <attr name="oneshot" format="boolean" />
    </declare-styleable>

    <!-- Represents a single frame inside an AnimationDrawable. -->
    <declare-styleable name="AnimationDrawableItem">
        <!-- Amount of time (in milliseconds) to display this frame. -->
        //单帧的显示时间 单位毫秒
        <attr name="duration" format="integer" />
        <!-- Reference to a drawable resource to use for the frame.  If not
             given, the drawable must be defined by the first child tag. -->
             //当前帧显示的图片资源
        <attr name="drawable" format="reference" />
    </declare-styleable>

它常用的几个方法:

  • void start() 开始播放动画
  • void stop() 停止播放动画
  • boolean isRunning() 判断当前AnimationDrawable是否正在播放
  • int getNumberOfFrames() 获取所有的帧数
  • Drawable getFrame(int index) 获取指定帧对应的Drawable对象
  • int getDuration(int i) 获取指定帧的显示持续时间
  • boolean isOneShot() 判断当前AnimationDrawable是否循环执行 true代表执行一次,false循环执行
  • void setOneShot(boolean oneShot) 设置AnimationDrawable是否循环执行
  • void addFrame(@NonNull Drawable frame, int duration) 为AnimationDrawable添加一帧

具体使用

我们来具体使用一下看下效果:
首先是通过xml实现

<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
   android:oneshot="true">

   <item android:drawable="@drawable/img0" android:duration="100"/>
   <item android:drawable="@drawable/img1" android:duration="100"/>
   <item android:drawable="@drawable/img2" android:duration="100"/>
   <item android:drawable="@drawable/img3" android:duration="100"/>
   <item android:drawable="@drawable/img4" android:duration="100"/>
   <item android:drawable="@drawable/img5" android:duration="100"/>
  //这里就展示几个item就好了 都是一样的显示时间就不重复贴了
</animation-list>

然后我们可以在xml文件中对ImageView的android:src/android:background属性直接设置使用或者在代码中设置也是一样的效果的。

    <ImageView
        android:id="@+id/iv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/frame_anim"
        android:layout_gravity="center"/>

代码中开始动画

		//通过设置android:background时,得到AnimationDrawable 用如下方法
        final AnimationDrawable animationDrawable = (AnimationDrawable) iv.getBackground();
        
        //通过设置android:src时,得到AnimationDrawable 用如下方法
        //AnimationDrawable animationDrawable = (AnimationDrawable) iv.getDrawable();

		btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                animationDrawable.start();
            }
        });
        
        btn2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                animationDrawable.stop();
            }
        });

这里有个地方要注意下,当我们设置android:oneshot为true时,动画已经播放一次完了之后,需要再次播放动画,这时候我们需要先调用stop()方法之后再调用start(),不然会停在最后一帧。
效果图:

java代码实现:

        final AnimationDrawable animationDrawable = new AnimationDrawable();
        animationDrawable.setOneShot(true);
        for (int i = 0; i <= 83; i++) {
            int id = getResources().getIdentifier("img" + i, "drawable", getPackageName());
            Drawable drawable = getResources().getDrawable(id);
            animationDrawable.addFrame(drawable, 100);
        }
        iv.setBackground(animationDrawable);
        
		btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                animationDrawable.start();
            }
        });
        
        btn2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                animationDrawable.stop();
            }
        });

这里对通过文件名拿到对应资源id的方法做个简单的说明:

/**
     * Return a resource identifier for the given resource name.  A fully
     * qualified resource name is of the form "package:type/entry".  The first
     * two components (package and type) are optional if defType and
     * defPackage, respectively, are specified here.
     * 
     * 

Note: use of this function is discouraged. It is much more * efficient to retrieve resources by identifier than by name. * * @param name The name of the desired resource. * @param defType Optional default resource type to find, if "type/" is * not included in the name. Can be null to require an * explicit type. * @param defPackage Optional default package to find, if "package:" is * not included in the name. Can be null to require an * explicit package. * * @return int The associated resource identifier. Returns 0 if no such * resource was found. (0 is not a valid resource ID.) */ public int getIdentifier(String name, String defType, String defPackage) { return mResourcesImpl.getIdentifier(name, defType, defPackage); }

第一个参数就是文件名,第二个参数是资源所在的文件类型,第三个参数就是包名。
特别注意:
在我们使用逐帧动画时,要避免使用大尺寸的图片,以免造成OOM。
到此逐帧动画就介绍完了,谢谢。

你可能感兴趣的:(Android动画)