2011-12-21 78 views

回答

1

我有完全相同的問題。
目前我正在使用onDraw方法從ImageView派生的自定義類播放動畫,我從資源文件夾中讀取一個圖像並將該圖像分配給畫布,每次檢查具體時間(在我的情況下爲60ms)經過並決定是否必須在最後顯示新圖像我調用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); 

在資產我有文件夾在該文件夾中的「動畫1」我有212 .PNG images(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) – 2011-12-22 14:03:07

+0

謝謝!我也發現你可以通過使用併發線程中填充的固定大小的幀緩衝區來提高性能。 – babb517 2011-12-26 22:18:03

+0

@ babb51​​7你能分享你的代碼與固定大小的幀緩衝區和併發線程嗎? – pzagor2 2012-01-17 20:40:20

相關問題