在android中显示大型预渲染动画的首选方法是什么?

时间:2011-12-21 17:10:58

标签: android animation

我有一系列逐帧动画,这些动画将被合并到一个程序中(3个动画,每个动画200-300帧)。在Android SDK中显示这些内容的最佳方式是什么?我尝试使用动画列表,但这些似乎想要同时缓冲所有图像,导致设备内存不足。

1 个答案:

答案 0 :(得分:1)

我遇到了完全相同的问题 目前我正在使用我在onDraw方法中从ImageView派生的自定义类来播放动画我从assets文件夹中读取了一个图像并将该图像分配给画布,每次检查特定时间(在我的情况下为60毫秒)是否已经过去,决定是否必须在最后显示新图像我调用postInvalidate()以便再次调用onDraw。 这种方法在我的HTC Desire上运行良好,但我没有机会在规格较低的设备上进行测试 如果没有人提供更好的解决方案,我就无法发布我的代码,以便其他人可以发表评论。

编辑:

    public class AnimationView extends ImageView
    {
private static final String TAG = "AnimView";
//public fields
public String STRING_FORMAT_FOR_PADDING = "%04d";
private String FILE_TYPE = "png";
public boolean STOP_AT_LAST_FRAME = true;
public int DELAY = 60; //delay between frames in milliseconds

//private fields
private boolean mIsPlaying = false;
private boolean mStartPlaying = false;
private Context mContext = null;
private int play_frame = 0;
private long last_tick = 0;
private Bitmap curentFrame = null;
private String dir;
private String prefix;
private int numberOfFrames;
private AnimationViewAnimFinished finishListener;
public AnimationView(Context context, AttributeSet attrs)
{
    super(context, attrs);
    mContext = context;  
}

public void setUpAnimation(String dir, String prefix, int numberOfFrames)
{
    this.dir = dir;
    this.prefix = prefix;
    this.numberOfFrames = numberOfFrames;
    curentFrame = loadImage(1);  //set first frame of animation to curent frame

}

public void setAnimationFinishListener(AnimationViewAnimFinished finishListener)
{
    this.finishListener = finishListener;
}

@Override
protected void onDraw(Canvas c)
{
    //Log.d(TAG, "onDraw called");
    if (mStartPlaying)
    {
        Log.d(TAG, "starting animation...");
        play_frame = 1;
        mStartPlaying = false;
        mIsPlaying = true;
        c.drawBitmap(curentFrame,  0, 0, null); // blink fix
        postInvalidate();
    }
    else if (mIsPlaying)
    {
        if (play_frame >= numberOfFrames)
        {
            mIsPlaying = false;
            if (STOP_AT_LAST_FRAME)
            {
                c.drawBitmap(curentFrame,  0, 0, null);
            }
            if (finishListener != null)
                finishListener.animationFinished(); //finish callback called
        }
        else
        {
            long time = (System.currentTimeMillis() - last_tick);
            int draw_x = 0;
            int draw_y = 0;
            if (time >= DELAY) //the delay time has passed. set next frame
            {
                Log.d(TAG, "drawing frame number:"+play_frame+" signature:"+curentFrame.toString());
                last_tick = System.currentTimeMillis();
                play_frame++;
                curentFrame = loadImage(play_frame);
            }
            c.drawBitmap(curentFrame,  draw_x, draw_y, null);
            postInvalidate();
        }
    }
    else //before animation starts ... drawing first frame
    {
        c.drawBitmap(curentFrame,  0, 0, null);
    }
}

private Bitmap loadImage(int numFrame)
{
    long startOne = android.os.SystemClock.uptimeMillis();
    String name =dir+ prefix + String.format(STRING_FORMAT_FOR_PADDING, numFrame)+"."+FILE_TYPE;

    InputStream ins = null;
    try {
        ins = mContext.getAssets().open(name);
    } catch (IOException e) {
        e.printStackTrace();
    }
    Bitmap d = BitmapFactory.decodeStream(ins);
    long endOne = android.os.SystemClock.uptimeMillis();
    Log.d(TAG,name+" frame decoded in: "+String.valueOf(endOne-startOne)+" ms");
    return d;

}

//set flag for starting animation to true and inicicate redraw
public void playAnimation()
{
    Log.d(TAG,"Play animation + invalidate()");
    mStartPlaying = true;
    postInvalidate();
}

//callack class for method restaurants
public static abstract class AnimationViewAnimFinished{
    public abstract void animationFinished();
}

}

在onCreate活动方法中我有:

    animationHolder = (AnimationView)findViewById(R.id.imageViewAnimationHolderService);
    animationHolder.setUpAnimation("animation1/", "frame_", 212);
    animationHolder.setAnimationFinishListener(myAnimationFinishListener);

在资产中我在该文件夹中有“animation1”文件夹我有212个.png图像命名(frame_0001.png,frame_0002.png,frame_0003.png,...,frame_0212.png)

当我开始制作动画时,我打电话:

    animationHolder.playAnimation();

这是动画完成侦听器的代码:

        AnimationViewAnimFinished myAnimationFinishListener = new AnimationViewAnimFinished() {

    @Override
    public void animationFinished() {
        Log.d(TAG,"animation finished");

    }
};