What I'm trying to achieve:
This is the first time I've used a SurfaceView, mulitthreading and a touch events. I'm trying to mask a rectangular bitmap image using a circular bitmap mask. I've been attemping to do this in a thread inside a SurfaceView. This SurfaceView also has an onTouch() method where when I drag the image it will move relative to the mask which will remain stationary.
The problem:
The mask works with the following code but only on the first iteration of the while loop. When it hits unlockCanvasAndPost(canvas) the second time around it overlays the mask as an image on top of the underlying bitmap and masking ceases taking effect. Fixed, still having problems with the redraw in the ontouch event - see below.
@Override
public void run() {
while(isRunnable){
// draw to the canvas
//if the surface isn't available go back to the top of the loop
if(!surfaceHolder.getSurface().isValid()){
continue;
}
result = Bitmap.createBitmap(maskImage.getWidth(), maskImage.getHeight(), Bitmap.Config.ARGB_8888);
//lock the canvas before trying to draw to it
canvas = surfaceHolder.lockCanvas();
maskPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
maskPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
Canvas tempCanvas = new Canvas(result);
//draw the bitmaps to the canvas
canvas.drawARGB(255, 255, 255, 255);
tempCanvas.drawBitmap(userIconImage, imageX, imageY, null);
tempCanvas.drawBitmap(maskImage, maskX, maskY, maskPaint);
maskPaint.setXfermode(null);
canvas.drawBitmap(result,0,0,new Paint());
surfaceHolder.unlockCanvasAndPost(canvas);
result = null;
}
}// run()
What I've tried:
This basically works. But when I drag to reposition the imgage in onTouch() I get traces of the previously drawn image. According to android.developer.com you can avoid this by using drawBitmap() Canvas and Drawables - SurfaceView section. This is what I'm trying to do, but apparently incorrectly. I also don't like that I have to continually create objects inside the while loop and would like to avoid it if possible.
My onTouch() method is currently like so:
@Override
public boolean onTouch(View v, MotionEvent motionEvent) {
try{
Thread.sleep(50);
}catch (InterruptedException e){
e.printStackTrace();
}
switch (motionEvent.getAction()){
case MotionEvent.ACTION_MOVE:
imageX = motionEvent.getX();
imageY = motionEvent.getY();
break;
}
return true;
}