2011-12-21 3 views
1

私は、プログラムに組み込む一連のフレームごとのアニメーションを用意しています(各アニメーションは200-300フレームで3回)。 Android SDKにこれらを表示する最良の方法は何ですか?私はアニメーションリストを使用しようとしましたが、これらは同時にすべてのイメージをバッファリングして、デバイスのメモリが不足するように思えます。大きな事前レンダリングされたアニメーションをアンドロイドに表示するには、どのような方法が適していますか?

答えて

1

私はまったく同じ問題を抱えていました。
onDrawメソッドのImageViewから派生した私のカスタムクラスでアニメーションを再生している瞬間、資産フォルダから画像を1つ読み込み、その画像をキャンバスに割り当てます。特定の時間(私の場合は60ms)経過し、最後に新しいイメージを表示する必要があるかどうかを判断するには、postInvalidate()を呼び出して、onDrawが再び呼び出されるようにします。 この方法はHTC Desireで問題なく動作していますが、低仕様のデバイスでテストする機会がありません。
もっと良い解決策を提供する人がいない場合、他の人がコメントできるように自分のコードを投稿することはできません。

EDIT:資産の

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

は私が212 .PNGを持ってそのフォルダ内の「animation1を」フォルダがあります:アクティビティののonCreateメソッドで

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(); 
} 

}

私はこれを持っています名前のついた画像(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"); 

    } 
}; 
+0

あなたのコードを投稿してくださいを。 :c) –

+0

ありがとう!私はまた、同時スレッドで実装された固定サイズのフレームバッファを使用してパフォーマンスを向上させることができることも発見しました。 – babb517

+0

@ babb51​​7固定サイズのフレームバッファと並列スレッドでコードを共有できますか? – pzagor2

関連する問題