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