2010-06-01 96 views
14

我有一個自定義視圖,填充我的整個屏幕。 (鋼琴鍵盤) 當用戶觸摸該按鍵時,會導致調用invalidate(),並且整個鍵盤都會重新繪製,以便用觸摸的按鍵顯示新狀態。Android:如何讓自定義視圖部分重繪?

目前該視圖非常簡單,但我打算添加一些更漂亮的圖形。由於整個鍵盤都是動態呈現的,這會使整個鍵盤的重繪變得更加昂貴。

所以我想,讓我們看看部分重繪。現在我打電話invalidate(Rect dirty)與正確的髒區域。如果確實需要部分重繪,我將onDraw(Canvas canvas)方法設置爲僅在髒區域繪製關鍵點。這導致這些鍵被繪製,但鍵盤的其餘部分完全是黑色的/根本不繪製。

我錯在期待調用invalidate(Rect dirty)會「緩存」當前canvas,並且只允許「在髒區域中繪圖」?

有什麼辦法可以實現我想要的? (A辦法「緩存」畫布和重繪髒區「

回答

18

當前不錯的解決方法是手動緩存滿畫布爲位圖:

private void onDraw(Canvas canvas) 
{ 
    if (!initialDrawingIsPerformed) 
    { 
      this.cachedBitmap = Bitmap.createBitmap(getWidth(), getHeight(), 
      Config.ARGB_8888); //Change to lower bitmap config if possible. 
      Canvas cacheCanvas = new Canvas(this.cachedBitmap); 
      doInitialDrawing(cacheCanvas); 
      canvas.drawBitmap(this.cachedBitmap, 0, 0, new Paint()); 
      initialDrawingIsPerformed = true; 
    } 
    else 
    { 
      canvas.drawBitmap(this.cachedBitmap, 0, 0, new Paint()); 
      doPartialRedraws(canvas); 
    } 
} 

Ofcourse,你需要存儲的信息關於如何重繪自己,最好不要每次都使用新的Paint,但這些都是細節。

另請注意:位圖對您的應用程序的內存使用情況非常重要當我緩存一個View時,一個卷軸,這就像設備的高度的5倍,因爲它使用> 10MB內存!

+1

嗯,我不喜歡這solutnio,因爲他的鍵部分繪製的原因是因爲他應該首先有hiscanvas的完整繪製無論如何。因此,問題是爲什麼他的畫布首先不能正確繪製。 – 2012-11-08 18:55:01

+1

我需要注意的是,我現在明白,當你用一個骯髒的'rect'調用'invalidate'時,你可以使用普通的繪圖代碼,並且它應該只能實際執行髒'rect'中的繪製操作。 'Canvas'放棄了'rect'之外的操作。儘管如此,這意味着你自己的許多代碼仍然呈現,並且在我的測試中使用HW加速比完全渲染視圖要慢。 – Peterdk 2014-01-07 01:45:40

+1

請注意,爲了將位圖繪製到畫布,繪製參數可以爲空,例如, 'canvas.drawBitmap(bitmap,0,0,null)'。 – greg7gkb 2016-03-19 06:01:25

5

爲了配合Peterdk的回答,您可以將您的操作保存在圖片中而不是位圖中。

  • 位圖將保存所有的像素,像 他說,它可能佔用大量的內存 。
  • 相機會保存 電話,像drawRect中,的drawLine等

這要看是什麼在你的應用程序非常沉重:很多平局操作,幾個繪製操作,但通過控制大量計算,很多空白/未使用的空間(喜歡圖片)等...

+0

不錯,將來看看這個! – Peterdk 2011-05-06 16:15:23

+0

不好意思。將'Picture'記錄'drawBitmap(bitmap)'調用?大概不是吧? – Yeung 2013-02-01 02:57:50

+0

請注意,圖片回放僅在軟件畫布上受支持,因此您不能對使用此圖層的視圖使用硬件圖層。 – greg7gkb 2016-03-19 03:23:36