2016-04-28 17 views
0

私の描画アプリケーションに問題があります。私は正しいタッチスクリーンをキャッチし、それらをキャンバスに描画する必要があります。ブラシのサイズを変更することは適切に機能しています。しかし、透明度の設定を変更すると、プログラムが正しく動作しません。前のパスの上に新しいパスが追加され、透明度が失われます。 Screenshot。どこで間違って行くことができますか?あなたの助けが必要です。ありがとうございました。SurfaceViewキャンバス透明度付き描画パス

これは私のSurfaceViewコードです:

public class PainterView extends SurfaceView implements SurfaceHolder.Callback { 

    private PainterThread painterThread; 
    private BrushParameters brushParameters; 
    private Bitmap bitmap; 


    public PainterView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     SurfaceHolder holder = getHolder(); 
     holder.addCallback(this); 

     brushParameters = new BrushParameters(); 

    } 

    @Override 
    public void surfaceCreated(SurfaceHolder surfaceHolder) { 
     setWillNotDraw(false); 
     getThread().setRunning(true); 
     getThread().start(); 
    } 

    @Override 
    public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int width, int height) { 
     if (bitmap == null) { 
      bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 
      getThread().setBitmap(bitmap, true); 
     } else { 
      getThread().setBitmap(bitmap, false); 
     } 

    } 

    @Override 
    public void surfaceDestroyed(SurfaceHolder surfaceHolder) { 
     getThread().setRunning(false); 
     boolean retry = true; 
     while (retry) { 
      try { 
       getThread().join(); 
       retry = false; 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
     painterThread = null; 
    } 

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

     switch (event.getAction()) { 
      case MotionEvent.ACTION_DOWN: 
       painterThread.startDraw(x, y); 
       break; 
      case MotionEvent.ACTION_MOVE: 
       painterThread.continueDraw(x, y); 
       break; 
      case MotionEvent.ACTION_UP: 
      case MotionEvent.ACTION_CANCEL: 
       painterThread.finishDraw(x, y); 
       break; 
     } 
     return true; 
    } 

    @Override 
    protected void onDraw(Canvas canvas) { 
     canvas.drawBitmap(bitmap, 0, 0, null); 
    } 

    public BrushParameters getBrushParameters() { 
     return brushParameters; 
    } 

    public void setBrushColor(int color) { 
     brushParameters.setColor(color); 
     getThread().setBrushParameters(brushParameters); 
    } 

    public void setBrushSize(int size) { 
     brushParameters.setSize(size); 
     getThread().setBrushParameters(brushParameters); 
    } 

    public void setBrushAlpha(int alpha) { 
     brushParameters.setAlpha(alpha); 
     getThread().setBrushParameters(brushParameters); 
    } 

    public PainterThread getThread() { 
     if (painterThread == null) { 
      painterThread = new PainterThread(getHolder(), this); 
     } 
     return painterThread; 
    } 
} 

そして、私のThreadクラス:助けを

public class PainterThread extends Thread { 

    private SurfaceHolder surfaceHolder; 
    private PainterView painterView; 
    private boolean running = false; 
    private Paint paint; 
    private Path path; 
    private Bitmap mBitmap; 
    private Canvas mCanvas; 

    private float lastX, lastY; 

    private static float TOUCH_TOLERANCE = 4; 

    public PainterThread(SurfaceHolder surfaceHolder, PainterView painterView) { 
     this.surfaceHolder = surfaceHolder; 
     this.painterView = painterView; 

     path = new Path(); 
     paint = new Paint(); 
     paint.setAntiAlias(true); 
     paint.setDither(true); 
     paint.setColor(Color.BLACK); 
     paint.setAlpha(255); 
     paint.setStyle(Paint.Style.STROKE); 
     paint.setStrokeWidth(5); 
     paint.setStrokeJoin(Paint.Join.ROUND); 
     paint.setStrokeCap(Paint.Cap.ROUND); 
    } 

    public void setRunning(boolean running) { 
     this.running = running; 
    } 

    @Override 
    public void run() { 
     Canvas mCanvas; 
     while (running) { 
      mCanvas = null; 
      try { 
       mCanvas = surfaceHolder.lockCanvas(null); 
       synchronized (surfaceHolder) { 
        if (mCanvas != null) { 
         mCanvas.drawBitmap(mBitmap, 0, 0, paint); 
         painterView.postInvalidate(); 
        } 
       } 
      } finally { 
       if (mCanvas != null) { 
        surfaceHolder.unlockCanvasAndPost(mCanvas); 
       } 
      } 
     } 
    } 

    public void setBitmap(Bitmap bitmap, boolean clear) { 
     mBitmap = bitmap; 
     if (clear) { 
      mBitmap.eraseColor(Color.WHITE); 
     } 
     mCanvas = new Canvas(mBitmap); 
    } 

    public void setBrushParameters(BrushParameters brushParameters) { 
     paint.setColor(brushParameters.getColor()); 
     paint.setAlpha(brushParameters.getAlpha()); 
     paint.setStrokeWidth(brushParameters.getSize()); 
    } 

    public void startDraw(float x, float y) { 
     path.reset(); 
     path.moveTo(x, y); 
     lastX = x; 
     lastY = y; 
    } 

    public void continueDraw(float x, float y) { 

     float dx = Math.abs(x - lastX); 
     float dy = Math.abs(y - lastY); 

     if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) { 
      path.quadTo(lastX, lastY, (x + lastX)/2, (y + lastY)/2); 
      mCanvas.drawPath(path, paint); 
      lastX = x; 
      lastY = y; 
     } 
    } 

    public void finishDraw(float x, float y) { 

     path.moveTo(x, y); 
     mCanvas.drawPath(path, paint); 
    } 
} 

感謝。私は問題の原因を見つけるためにfiew日を失った...

答えて

0

私はSurfaceViewを取り除くことをお勧めします。混乱しているコードがあります(例:setBitmap()mCanvasに設定されていますが、それはループ内でrun()で上書きされています)、自分の人生をもっと難しくしていると思います。

SurfaceViewsには、サーフェスとビューの2つの部分があります。サーフェスは、(デフォルトで)ビューレイヤの背後にある別のレイヤーです。 SurfaceViewのView部分は、通常、透明な穴であり、後ろのSurfaceレイヤーに "透けて見える"ことができます。

あなたの場合は、ビューオブジェクトでonDraw()をオーバーライドしているので、実際にビューを描画しています。あなたの別のスレッドでは、同じビットマップをサーフェイス上に描画しています。ビットマップに透明ピクセルがある場合でも、2つの同一のビットマップが重ねて表示されます。

不幸のレシピである、同時に実行される2つのスレッド間でビットマップと可能であればCanvasを共有しているようです。

SurfaceViewを取り除き、ちょうどcustom Viewを使うと、私はすべてが理にかなっていると思います。もう1つの方法は、onDraw()を取り除き、postInvalidate()を呼び出してSurface上のすべてを実行することですが、ハードウェアアクセラレーションによるレンダリングを利用するには、カスタムViewを使用する方がよいでしょう。

+0

ありがとうございました。それは働いている –

関連する問題