2013-07-19 50 views
0

我已經創建SurfaceView類用於對由onTouch方法的視圖繪製...我已經閱讀並瞭解了SurfaceView和製圖活動一些示例代碼,並建立了下面的類:機器人SurfaceView的onDraw方法停止處理隨機

public class DrawingSurface extends SurfaceView implements 
     SurfaceHolder.Callback{ 
    private DrawingThread drawingthread; 
    public Paint mPaint; 

    private Bitmap mBitmap; 
    private Canvas mCanvas; 
    private Path mPath; 
    private Paint mBitmapPaint; 

    private float cx = 0, cy = 0; 
    private boolean easer = false; 
    private boolean touch = false; 
    private Paint mEarserPaint; 
    int count = 0; 


    public DrawingSurface(Context context, AttributeSet attrs) { 
     super(context, attrs); 

     getHolder().addCallback(this); 

    } 

    public DrawingSurface(Context context) { 
     super(context); 

     getHolder().addCallback(this); 

    } 

    @Override 
    protected void onSizeChanged(int w, int h, int oldw, int oldh) { 
     super.onSizeChanged(w, h, oldw, oldh); 
     System.out.println("onSizeChange"); 
     mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); 
     mCanvas = new Canvas(mBitmap); 
    } 

    @Override 
    public void surfaceChanged(SurfaceHolder holder, int format, int width, 
      int height) { 
     System.out.println("onSurfaceChange"); 

    } 

    @Override 
    public void surfaceCreated(SurfaceHolder holder) { 
     System.out.println("onSurfaceCreated"); 
     // For drawing that is called in the onDraw method 
     mPaint = new Paint(); 
     mPaint.setAntiAlias(true); 
     mPaint.setDither(true); 
     mPaint.setColor(0xF0000000); 
     mPaint.setStyle(Paint.Style.STROKE); 
     mPaint.setStrokeJoin(Paint.Join.ROUND); 
     mPaint.setStrokeCap(Paint.Cap.ROUND); 
     mPaint.setStrokeWidth(12); 


     mEarserPaint = new Paint(); 
     mEarserPaint.setAntiAlias(true); 
     mEarserPaint.setDither(true); 
     mEarserPaint.setColor(0xF0000000); 
     mEarserPaint.setStyle(Paint.Style.STROKE); 
     mEarserPaint.setStrokeJoin(Paint.Join.ROUND); 
     mEarserPaint.setStrokeCap(Paint.Cap.ROUND); 
     mEarserPaint.setStrokeWidth(12); 


     mPath = new Path(); 
     mBitmapPaint = new Paint(Paint.DITHER_FLAG); 

     drawingthread = new DrawingThread(getHolder(), this); 
     drawingthread.setRunning(true); 
     drawingthread.start(); 
     setFocusable(true); 


    } 

    @Override 
    public void surfaceDestroyed(SurfaceHolder holder) { 
     System.out.println("OnDestroy"); 
     boolean retry = true; 
     drawingthread.setRunning(false); 
     while (retry) { 
      try { 
       drawingthread.join(); 
       retry = false; 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 

     } 
    } 

    @Override 
    public void onDraw(Canvas canvas) { 

     // on earser mode draw circal on touch 
     if (easer && touch) { 
      canvas.drawColor(0xFFAAAAAA); 
      canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint); 
      canvas.drawCircle(cx, cy, 50, mEarserPaint); 

     } else { 
      canvas.drawColor(0xFFAAAAAA); 
      canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint); 
      canvas.drawPath(mPath, mPaint); 
     } 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent event) { 
     float x = event.getX(); 
     float y = event.getY(); 

     // get the touch postion for drawing the circal 
     cx = event.getX(); 
     cy = event.getY(); 

     switch (event.getAction()) { 
     case MotionEvent.ACTION_DOWN: 
      touch_start(x, y); 
      touch = true; 
      invalidate(); 
      break; 
     case MotionEvent.ACTION_MOVE: 
      touch_move(x, y); 
      invalidate(); 
      touch = true; 
      break; 
     case MotionEvent.ACTION_UP: 
      touch_up(); 
      invalidate(); 
      touch = false; 
      break; 
     } 
     return true; 
    } 

    private float mX, mY; 
    private static final float TOUCH_TOLERANCE = 4; 

    private void touch_start(float x, float y) { 
     mPath.reset(); 
     mPath.moveTo(x, y); 
     mX = x; 
     mY = y; 
    } 

    private void touch_move(float x, float y) { 
     float dx = Math.abs(x - mX); 
     float dy = Math.abs(y - mY); 
     if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) { 
      mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2); 
      mX = x; 
      mY = y; 
     } 

     if (easer) 
      mCanvas.drawPath(mPath, mPaint); 
    } 

    private void touch_up() { 
     mPath.lineTo(mX, mY); 
     mCanvas.drawPath(mPath, mPaint); 
     mPath.reset(); 
    } 

    public void onAttributeChange(Paint paint, boolean e) { 
     mPaint = paint; 
     easer = e; 
    } 

    public Bitmap getDrawingSurface() { 
     return mBitmap; 
    } 

} 

而這是用於SurfaceView線程類:

public class DrawingThread extends Thread { 
    private SurfaceHolder drawingHolder; 
    private DrawingSurface drawingSurface; 
    private boolean run = false; 

    public DrawingThread(SurfaceHolder surfaceholder, DrawingSurface surfaceview) { 
     drawingHolder = surfaceholder; 
     drawingSurface = surfaceview; 
    } 

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

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

     } 
    } 

} 

此工作正常形式開始,但它停止在一段時間後的視圖(未碰撞)隨機繪圖(在5秒到3分鐘)時,我不斷繪圖..我的數字是onDraw方法st op處理,我不知道爲什麼,在日誌中沒有例外,onDestory方法不會在onDraw停止響應我的touch時調用。

希望你能幫助我解決這個問題。

回答

0

我不知道爲什麼你有DrawingThread。您的DrawingSurface類重寫onDraw,並調用invalidate()來請求重畫。這應該足以做你想做的事情。

我會將DrawingThread註釋掉,看看它是否神奇地聚集在一起。我編寫了一個網絡白板應用程序,該應用程序從看起來像您開始的相同示例代碼開始。

+0

當我刪除Drawingthread的onDraw方法停止工作在所有的屏幕變黑,我不能畫任何東西。 我的理解是SurfaceView必須使用線程才能工作,與常規視圖不同,所以如果有一種方法可以實現SurfaceView而不需要線程plz,請向我提供一些示例,瞭解如何執行此操作。 – FinalDark

+0

我明白了。我的應用程序不是繪製在SurfaceView上,而是我從View開始編寫的類。 – spartygw