顾名思义,逐帧动画就是将一组图片资源一帧一帧播放,逐帧动画跟补间动画一样都可以通过XML或者Java代码实现。
当然不管哪种方式实现都离不开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>
它常用的几个方法:
我们来具体使用一下看下效果:
首先是通过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。
到此逐帧动画就介绍完了,谢谢。