欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android自定义控件:动画类---逐帧动画AnimationDrawable

程序员文章站 2022-03-26 08:48:31
...

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多张大图的时候很容易内存溢出。