2011-03-04 81 views
4

我想問一個已經在這裏解決過一次或兩次的問題,但沒有找到任何信息可以幫助我解決前幾天遇到的問題。LiveWallpaper SurfaceHolder.lockCanvas(Rect dirty)

我想爲使用畫布的android製作動態壁紙 - 它不需要圖形複雜到需要OpenGL。爲了簡單起見,假設它由堅實的背景和兩個較小的矩形組成。 繪圖由三個單獨的階段(在單線程):

  1. backgroundDraw()請求整個畫布鎖並在其上繪製純色
  2. DRAW1()請求部分(矩形R1)鎖定,並繪製僅在鎖定矩形
  3. DRAW2()請求部分(矩形R2)鎖定,並且只在被鎖定的矩形平

我測試多個的Android版本(包括仿真器和裝置):2.1,2.2,2.3.3。它似乎只適用於後者(這裏:http://home.elka.pw.edu.pl/~pgawron/include/Android/android_233.jpg)。在以前的Android版本中,SurfaceHolder.lockCanvas(Rect dirty)將調整大小(!)作爲參數傳遞給整個屏幕,並在整個屏幕上使用結果繪圖進行繪製(此處爲http://home.elka.pw.edu.pl/~pgawron/include/Android/android_22.jpg)。實際上,我可以看到每個矩形如何繪製(全屏):整個屏幕非常快速地改變它的顏色。

不幸的是,google無法找到lockCanvas(Rect dirty)用法的任何適當示例。下面我附上我的完整和唯一的類用於測試目的。完整的eclipse項目只需提供截圖即可訪問。

如果有人能夠最終幫助我並更正我的代碼(如果只有問題出現在我的代碼中),我將不勝感激。我真的浪費了太多時間。

BR,

彼得雷利

package sec.polishcode.test; 

import android.graphics.Canvas; 
import android.graphics.Color; 
import android.graphics.Paint; 
import android.graphics.Rect; 
import android.os.SystemClock; 
import android.service.wallpaper.WallpaperService; 
import android.util.Log; 
import android.view.SurfaceHolder; 

public class TestLiveWallpaper extends WallpaperService{ 

@Override 
public Engine onCreateEngine() { 
    return new MyEngine(); 
} 

class MyEngine extends Engine implements SurfaceHolder.Callback { 

    private final String LOGTAG = MyEngine.class.getSimpleName(); 
    private Paint backgroundPaint = new Paint(); 
    private Paint mPaint1 = new Paint(); 
    private Paint mPaint2 = new Paint(); 
    private long lastVisibilityOnChange; 

    private final Rect r1 = new Rect(20, 20, 60, 280); 
    private final Rect r2 = new Rect(70, 20, 110, 280); 

    public MyEngine() { 

     getSurfaceHolder().addCallback(this); 

     backgroundPaint.setColor(Color.YELLOW); 
     mPaint1.setColor(Color.LTGRAY); 
     mPaint2.setColor(Color.MAGENTA); 
    } 

    @Override 
    public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, 
      int arg3) { 
     drawSurface(); 
    } 

    @Override 
    public void surfaceCreated(SurfaceHolder arg0) { 
     Log.i(LOGTAG, "surfaceCreated"); 
    } 

    @Override 
    public void surfaceDestroyed(SurfaceHolder arg0) { 
     Log.i(LOGTAG, "surfaceDestroyed"); 
    } 

    @Override 
    public void onCreate(SurfaceHolder surfaceHolder) { 
     super.onCreate(surfaceHolder); 

     setTouchEventsEnabled(true); 
    } 

    @Override 
    public void onVisibilityChanged(boolean visible) { 
     if (!visible) 
      return; 

     lastVisibilityOnChange = SystemClock.elapsedRealtime(); 
     drawSurface(); 
    } 

    @Override 
    public void onOffsetsChanged(float xOffset, float yOffset, float xStep, 
      float yStep, int xPixels, int yPixels) { 

     if (SystemClock.elapsedRealtime() - lastVisibilityOnChange > 30) 
      return; 

     Log.i(LOGTAG, "onOffsetsChanged filtered"); 
     drawSurface(); 
    } 

    private void drawSurface() { 
     backgroundDraw(); 
     draw1(); 
     draw2(); 
    } 

    private void backgroundDraw() { 
     final SurfaceHolder holder = getSurfaceHolder(); 

     Canvas c = null; 
     try { 
      c = holder.lockCanvas(); 
      if (c != null) { 
       c.drawRect(holder.getSurfaceFrame(), backgroundPaint); 
      } 
     } finally { 
      if (c != null) 
       holder.unlockCanvasAndPost(c); 
     } 
    } 

    private void draw1() { 
     final SurfaceHolder holder = getSurfaceHolder(); 

     Canvas c = null; 
     try { 
      c = holder.lockCanvas(r1); 
      if (c != null) { 
       c.drawRect(r1, mPaint1); 
      } 
     } finally { 
      if (c != null) 
       holder.unlockCanvasAndPost(c); 
     } 
    } 

    private void draw2() { 
     final SurfaceHolder holder = getSurfaceHolder(); 

     Canvas c = null; 
     try { 
      c = holder.lockCanvas(r2); 
      if (c != null) { 
       c.drawRect(r2, mPaint2); 
      } 
     } finally { 
      if (c != null) 
       holder.unlockCanvasAndPost(c); 
     } 
    } 
} 
} 
+0

您是否發現過此問題的解決方案?我想知道如何爲livewallpaper使用髒矩形,但沒有任何運氣。 – YasuDevil 2011-08-05 20:46:04

回答

3

lockCanvas(矩形髒)是非常簡單的。請記住,Android表面默認情況下是雙緩衝的。這意味着您不僅需要重新繪製當前表面的髒區域,還需要重新繪製前一個表面的髒區域,以使其正常工作。這就是爲什麼lockCanvas()會調整你傳遞的矩形的大小:它告訴真正的髒區域是什麼。髒區域也可能因爲表面被丟棄和重新創建等而改變。使用lockCanvas(Rect)的正確方法是傳遞你的髒矩形,然後檢查它的新值並遵守它們。

+0

感謝您的解釋,這正是我的問題是......不幸的是檢查官方的API它並沒有說關於當整個屏幕很髒時自動調整髒Rect的任何東西 – 2013-09-25 23:28:36

+0

它當然會:「此功能可能選擇展開如果例如表面已被調整大小或者表面的先前內容不可用,則爲髒矩形。「 – 2013-09-26 00:08:27

+0

剛纔發現在Surface裏面看着SurfaceHolder – 2013-09-27 13:25:19