2011-04-14 166 views
1

我有一個閃爍問題。 這是我的代碼。Surfaceview問題

public class Tutorial2D3 extends Activity { 

Panel panel; 
/** Called when the activity is first created. */ 
@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    panel = new Panel(this); 
    setContentView(panel); 
} 

@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
    menu.add(1, 1, 1, "Clean Canvas"); 
    return super.onCreateOptionsMenu(menu); 
} 

@Override 
public boolean onMenuItemSelected(int featureId, MenuItem item) { 
    panel.cleanCanvas(); 
    return true; 
} 

class Panel extends SurfaceView implements SurfaceHolder.Callback { 
    TutorialThread thread; 
    Bitmap icon; 
    int iconWidth; 
    int iconHeight; 
    int touchX; 
    int touchY; 
    int mCount = 0; 

    public Panel(Context context) { 
     super(context); 
     icon = BitmapFactory 
       .decodeResource(getResources(), R.drawable.icon); 
     iconWidth = icon.getWidth(); 
     iconHeight = icon.getHeight(); 
     getHolder().addCallback(this); 
     thread = new TutorialThread(getHolder(), this); 
     setFocusable(true); 
    } 

    @Override 
    protected void onDraw(Canvas canvas) { 
     int x = touchX - (iconWidth/2); 
     int y = touchY - (iconHeight/2); 
     if(mCount>0) { 
      canvas.drawColor(Color.BLACK); 
      mCount--; 
     } 
     canvas.drawBitmap(icon, (x > 0 ? x : 0), (y > 0 ? y : 0), null);  
    } 

    @Override 
    public void surfaceChanged(SurfaceHolder holder, int format, int width, 
      int height) { 
     // TODO Auto-generated method stub 

    } 

    @Override 
    public void surfaceCreated(SurfaceHolder holder) { 
     thread.setRunning(true); 
     thread.start(); 
    } 

    @Override 
    public void surfaceDestroyed(SurfaceHolder holder) { 
     boolean retry = true; 
     thread.setRunning(false); 
     do { 
      try { 
       thread.join(); 
       retry = false; 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } while (retry); 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent event) { 
     switch (event.getAction()) { 
     case MotionEvent.ACTION_DOWN: 
      touchX = (int) event.getX(); 
      touchY = (int) event.getY(); 
      break; 
     case MotionEvent.ACTION_MOVE: 
      touchX = (int) event.getX(); 
      touchY = (int) event.getY(); 
      break; 
     case MotionEvent.ACTION_UP: 
      break; 
     default: 
      break; 
     } 
     return true; 
    } 

    private void cleanCanvas() { 
     mCount = 2; 
    } 
} 



class TutorialThread extends Thread { 
    private SurfaceHolder _surfaceHolder; 
    private Panel _panel; 
    private boolean _run = false; 

    public TutorialThread(SurfaceHolder surfaceHolder, Panel panel) { 
     _surfaceHolder = surfaceHolder; 
     _panel = panel; 
    } 

    public void setRunning(boolean run) { 
     _run = run; 
    } 

    @Override 
    public void run() { 
     Canvas c; 
     while (_run) { 
      c = null; 
      try { 
       c = _surfaceHolder.lockCanvas(null); 
       synchronized (_surfaceHolder) { 
        _panel.onDraw(c); 
       } 
      } finally { 
       if (c != null) { 
        _surfaceHolder.unlockCanvasAndPost(c); 
       } 
      } 
     } 
    } 
} 

}

繪製圖像閃爍。 看起來像是在一個點上繪製的位圖繪製在一個表面上,而不是另一個上,因此它看起來像閃爍,當我們觸摸action_up時繪製的位圖完成,這是一個實體圖像,不會閃爍。有人能幫我解決這個問題嗎? 感謝

回答

1

當你在一個SurfaceView的繪圖畫布,你必須始終表面的每一個像素。
在這裏,您並不總是清除onDraw()中的畫布,因此閃爍。

+0

這樣做會減慢繪圖部分。 – vivek 2011-04-15 04:32:30

+0

是的,但你沒有別的選擇,這就是SurfaceView的工作方式。 – 2011-04-20 13:45:44

1

你可以做的一件事是減輕這個(並且有點違背Guillaume :))是使用surfaceholder.lockCanvas(矩形),它只是畫布的指定矩形部分,然後繪製(但你必須繪製該矩形的每個像素)。這是從LunarLandar樣品撕開:

@Override 
    public void run() { 
     while (mRun) { 
      Canvas c = null; 
      try { 
       c = mSurfaceHolder.lockCanvas(Rectangle); 
       synchronized (mSurfaceHolder) { 
        if (mMode == STATE_RUNNING) updatePhysics(); 
        doDraw(c); 
       } 
      } finally { 
       // do this in a finally so that if an exception is thrown 
       // during the above, we don't leave the Surface in an 
       // inconsistent state 
       if (c != null) { 
        mSurfaceHolder.unlockCanvasAndPost(c); 
       } 
      } 
     } 
    } 
1

我沒有讀通過所有你的代碼,但我認爲this article會有所幫助。

製品的本質是,閃爍是由於雙緩衝,並且可以通過不拉絲的說法畫布而是用作畫布一個位圖,然後繪製位圖給ARG畫布被消除:

int myCanvas_w, myCanvas_h; 
Bitmap myCanvasBitmap = null; 
Canvas myCanvas = null; 
Matrix identityMatrix; 

@Override 
public void surfaceCreated(SurfaceHolder holder) { 

myCanvas_w = getWidth(); 
myCanvas_h = getHeight(); 
myCanvasBitmap = Bitmap.createBitmap(myCanvas_w, myCanvas_h, Bitmap.Config.ARGB_8888); 
myCanvas = new Canvas(); 
myCanvas.setBitmap(myCanvasBitmap); 

identityMatrix = new Matrix(); 
} 

@Override 
protected void onDraw(Canvas canvas) { 

paint.setStyle(Paint.Style.STROKE); 
paint.setStrokeWidth(3); 

//int w = myCanvas.getWidth(); 
//int h = myCanvas.getHeight(); 
int x = random.nextInt(myCanvas_w-1); 
int y = random.nextInt(myCanvas_h-1); 
int r = random.nextInt(255); 
int g = random.nextInt(255); 
int b = random.nextInt(255); 

paint.setColor(0xff000000 + (r << 16) + (g << 8) + b); 
myCanvas.drawPoint(x, y, paint); // <--------- Here's where you draw on your bitmap 

canvas.drawBitmap(myCanvasBitmap, identityMatrix, null); 
// ^---------- And here's where you draw that bitmap to the canvas 

}