2011-10-01 38 views
8

我從頭創建了一個自定義視圖。擴展View並被覆蓋onDraw()。 當動畫製作視圖時,我使用偏移生成了一個自定義動畫。 例如。如何在android中繪製動畫視圖?

while(!isOnTop){ 
mOffset++; 

//draw the component a a it higher using the offset 

if(position == 0) 
isOnTop==true; 
invalidate(); 

} 

這個想法是,我的幀來自它自我無效。問題是這個視圖的失效只能通過在同一個屏幕上滾動列表視圖來實現。

這個「共享失效()」會導致我的動畫滯後。所以有沒有一種方法超出這個滯後?

您是否有任何其他建議在該共享環境中執行動畫? 使用計算偏移量的單獨線程創建動畫也需要強制失效()調用來顯示動畫(如果我錯了,請糾正我)。

是唯一的解決方案執行動畫在例如10個失效請求與更大的步驟?這將緩解滯後,但我認爲我可以使用不同的方法。

回答

4

由於這個問題有一些興趣,我會回覆。

最好的方法是有一個單獨的畫布線程。 「分離」畫布只能通過SurfaceView才能實現。 LunarLanding是一個非常好的例子。每個幀的計算與主視圖分開計算時間分開,而不是繪製時間。因此速度更快,即使在例如頂部的常規視圖和底部的動畫視圖的組合下也是如此。

但是,如果您處於共享環境中,則必須設置間隔。該時間間隔用於FPS上限。如果你沒有設置FPS上限,那麼CPU將運行得很好,如果它是獨立的,管理將獲得良好的動畫到SurfaceView。以60fps或甚至更低的幅度進行封蓋將有助於在沒有CPU過載的情況下高效地繪製所有視圖。

因此,請參閱API演示中的Lunar Landing繪圖線程並設置FPS上限。

private long timeNow; 
    private long timeDelta; 
    private long timePrevFrame; 

    private void capFps(int fps) { 
      timeNow = System.currentTimeMillis(); 
      timeDelta = timeNow - timePrevFrame;   

      try { 

// ps的你總是可以設置16,而不是爲60FPS 1000/FPS避免計算每次

Thread.sleep((1000/fps) - timeDelta); 
      } catch (InterruptedException e) { 

      } 

      timePrevFrame = System.currentTimeMillis(); 
    } 

然後將繪圖線程會是這個樣子:

@Override 
    public void run() { 
     Canvas c; 

     while (run) { 
      c = null; 
      sleepFps(60, false); 
      try { 
       synchronized (surfaceHolder) { 
        c = surfaceHolder.lockCanvas(null); 
        widgetView.doDraw(c); 
       } 
      } finally { 
       if (c != null) { 
        surfaceHolder.unlockCanvasAndPost(c); 
       } 
      } 

     } 
    } 
+0

對不起,這是*路*要複雜得多,通常需要和SurfaceView有很多妥協,使得它往往不是最好的解決方案。 – hackbod

+0

是的,它是最好的一起擁有多個動畫視圖。問題是什麼是「最好」的方式,儘管謝謝你的回答 – weakwire

+0

這其實是我從j2me熟悉的方式。如果你不喜歡計算,你總是可以跳過它並在一段時間內睡覺。 –

23

「什麼是最好的」當然很大程度上取決於你想要做什麼。你沒有說你想要完成什麼,所以我們只能猜測什麼可能是最適合你的。

這裏有一些簡單的事情:

下面是使用處理程序的簡單重複無效:

long mAnimStartTime; 

Handler mHandler = new Handler(); 
Runnable mTick = new Runnable() { 
    public void run() { 
     invalidate(); 
     mHandler.postDelayed(this, 20); // 20ms == 60fps 
    } 
} 

void startAnimation() { 
    mAnimStartTime = SystemClock.uptimeMillis(); 
    mHandler.removeCallbacks(mTick); 
    mHandler.post(mTick); 
} 

void stopAnimation() { 
    mHandler.removeCallbacks(mTick); 
} 
+1

invalidate()不是即時的。可能需要超過20ms,因爲有很多視圖需要失效。視圖必須等到所有視圖都完成(至少在3.0之前)。然後postDelayed會引入更多的滯後。限制fps這種方式並不好。如果我錯了,請糾正我。 – weakwire

+2

不是。如果invalidate()花費的時間超過20ms,那麼您在結構化視圖層次結構方面遇到嚴重問題。標準平臺中的絕大多數窗口中的動畫使用invalidate()的常規視圖,並且可以達到60fps。你只需要確保你不會在你的視圖層次結構中做任何事情,比如在彼此之上有多個不透明的位圖,或者縮放使得繪製它們變得緩慢......但是不管怎樣你都不想這樣做。 – hackbod

+12

是不是20ms 50fps? –

相關問題