Android自定义控件:动画类---逐帧动画AnimationDrawable
1:概述
Android动画包括View Animation(视图动画)和Property Animator(属性动画),而View Animation包括Tween Animation(补间动画)和Frame Animation(逐帧动画);补间动画主Animation(ScaleAnimation、 AlphaAnimation、RotateAnimation、TranslateAnimation)为主,而逐帧动画则是以AnimationDrawable为主。
2:定义逐帧动画
定义逐帧动画非常简单,只要在<animation-list.../>中使用<item.../>子元素定义动画的全部帧,并指定各帧的持续时间即可
<?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/scenery1"
android:duration="1000"/>
<item
android:drawable="@drawable/scenery2"
android:duration="1000"
/>
<item
android:drawable="@drawable/scenery3"
android:duration="1000"
/>
<item
android:drawable="@drawable/scenery4"
android:duration="1000"
/>
<item
android:drawable="@drawable/scenery5"
android:duration="1000"
/>
</animation-list>
上面语法格式中android:onshot控制该动画是否循环播放,如果该参数指定为true,则动画将不会循环播放;否则该动画将会循环播放。每个<item.../>子元素增加一帧。接下来就可用ImageView把AnimationDrawable显示出来,习惯上把AnimationDrawable设成ImageView的背景即可。
需要指出的是:AnimationDrawable代表的动画默认是不播放的,必须在程序中启动动画播放才可以。AnimationDrawable提供如下两个方法开始、停止动画。
1> start():开始播放动画
2> stop(): 停止播放动画
3:添加的帧数过多产生OOM的解决
<span style="font-size:18px;">private void loadBitmap(){
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPurgeable=true;
options.inInputShareable=true;
//设置该属性可获得图片的长宽等信息,但是避免了不必要的提前加载动画
options.inJustDecodeBounds=false;
InputStream is=null;
int[] raw={
R.raw.scenery1,R.raw.scenery2,R.raw.scenery3,R.raw.scenery4,R.raw.scenery5
};
Bitmap[] mbitMap=new Bitmap[5];
for(int i=0,j=0;i<5&&j<5;i++,j++){
is=getResources().openRawResource(raw[i]);
Bitmap bitmap =BitmapFactory.decodeStream(is, null, options);
mbitMap[j]=bitmap;
}
AnimationDrawable clipDrawable= new AnimationDrawable();
for(int i=0;i<5;i++){
clipDrawable.addFrame(new BitmapDrawable(mbitMap[i]), 50);
}
clipDrawable.setOneShot(false);
animationDrawable=clipDrawable;
iv_frame.setBackground(animationDrawable);
}</span>
setbackgroundResource()这种方法在设置animationDrawable动画的时候,是会在java层和native层产生两个实例的,而高像素bitmap图是特别占内存的,所以容易产生内存溢出问题,而我找到的最好解决方法是,不适用setBackgroundResource()这个方法而是首先使用decodeStream()这个方法读入bitmap字节码的流,而这个方法与decodeResource等其他方法相比,最好的地方在于它仅仅在native层也就是底层产生一个实例,但不会在java层使用createBitMap()方法产生实例,因此极大地减少了内存的占用,否则当读入20多张大图的时候很容易内存溢出。