I have an activity class, which I want to show a small dynamic content with translucent background on top of a main content, that is something like a moving overlay. I use a SurfaceView descendant for this purpose. For the simplicity I'm trying to code a POC, so I draw an arc in the surface view and rotate it, and move slightly on timer events. The problem is that the code works ok, only if rotation is involved. When I add a shift by (x, y) to change the surface view position, it begins to draw with black opaque rectangle as background. The code is presented below:
public class AndroidActivity extends Activity
{
private RelativeLayout layout;
private OverlayView mOverlay;
private Handler mHandler = new Handler();
private Timer timer = new Timer();
private SurfaceHolder surfaceHolder;
private int degrees = 0;
private int x = 100;
private int y = 200;
@Override
protected void onCreate(Bundle b)
{
super.onCreate(b);
setContentView(R.layout.main_view); // inflate main view
layout = (RelativeLayout) findViewById(R.id.mainview); // get parent layout
mOverlay = new OverlayView(this); // create the surface view descendant
// prepare layout parameters for the surface view
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(50, 50);
params.leftMargin = x;
params.topMargin = y;
mOverlay.setLayoutParams(params); // apply parameters
// next 2 lines ensure transparent background mode
mOverlay.setZOrderOnTop(true);
mOverlay.getHolder().setFormat(PixelFormat.TRANSLUCENT);
// add the surface view into the parent layout
layout.addView(mOverlay);
// lets start dynamic motion
timer.schedule(new DebugTimerTask(), 500, 500);
}
private class OverlayView extends SurfaceView implements SurfaceHolder.Callback
{
private Paint mPaint = new Paint();
public OverlayView(Context context)
{
super(context);
surfaceHolder = getHolder();
surfaceHolder.addCallback(this);
}
protected void doDraw(Canvas canvas)
{
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mPaint.setStrokeWidth(1);
// will draw semitransparent yellow arc
mPaint.setColor(Color.YELLOW);
mPaint.setAlpha(128);
RectF oval = new RectF(0, 0, +50, +50);
canvas.drawColor(0, android.graphics.PorterDuff.Mode.CLEAR);
canvas.drawArc(oval, degrees, 90, true, mPaint);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height)
{
}
@Override
public void surfaceCreated(SurfaceHolder holder)
{
setZOrderOnTop(true);
holder.setFormat(PixelFormat.TRANSLUCENT);
}
@Override
public void surfaceDestroyed(SurfaceHolder holder)
{
}
}
private class DebugTimerTask extends TimerTask
{
public void run()
{
mHandler.post(new Runnable()
{
@Override
public void run()
{
degrees += 10; // rotate a bit
x += 1; // move a bit
y += 2;
Canvas canvas = null;
// if next lines are commented, code works almost perfectly:
// rotation of semitransparent arc over content beneath,
// but I need to move the overlay, so
// if they are not commented, the overlay's background becomes black
// variant A: doesn't work
//RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(50, 50);
//params.leftMargin = x;
//params.topMargin = y;
//mOverlay.setLayoutParams(params);
// variant B: doesn't work
//mOverlay.layout(x, y, x + 50, y + 50);
try
{
synchronized(surfaceHolder)
{
canvas = surfaceHolder.lockCanvas(null);
if(canvas != null)
{
mOverlay.doDraw(canvas);
}
}
}
finally
{
if(canvas != null)
{
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
});
}
}
}
What is a proper way to move a surface view with transparent background?