Reputation: 2369
I have a Canvas
on which I am drawing lines bewteen points in a onTouchEvent()
. When the user makes an invalid selection on where to place the line, I draw a red line instead of a black one. However I want the red line to fade away over the next 500-1000ms.
I haven't been able to figure out how to do it, and if it is even possible to animate a single line inside a Canvas
.
I have split the dots, the valid black lines and the invalid red line(s) between 3 different bitmaps inside my:
public void onDraw(Canvas canvas) {
// Fade Red Line
canvas.drawBitmap(fBitmap, 0, 0, null);
// Lines
canvas.drawBitmap(mBitmap, 0, 0, null);
// Dots
canvas.drawBitmap(iBitmap, 0, 0, null);
}
and inside my onTouch function are my drawLines()
.
I was wondering if I can use an AlphaAnimation for this, or if I have to use a timer system to loop over the fBitmap
with the red line I want to fade out over time.
Any Ideas?
EDIT: Okay here's how I eventually solved it after coming back to it a year later:
I implemented a SurfaceView and created a thread to continuously update the Canvas.
@Override
public void run() {
while (isRunning) {
if (!surfaceHolder.getSurface().isValid()) {
continue;
}
decreaseLineOpacity();
drawLinesInvalid();
/* Other things to draw*/
Canvas canvas = surfaceHolder.lockCanvas();
canvas.drawBitmap(fBitmap, centerPointWidth, centerPointHeight, null);
// mBitmap is the middleground with the line that fades away.
// and is bound to mCanvas for drawing
canvas.drawBitmap(mBitmap, centerPointWidth, centerPointHeight, null);
canvas.drawBitmap(iBitmap, centerPointWidth, centerPointHeight, null);
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
And then the methods that take care of changing the opacity and drawing the line, I store each line I draw in a Queue, until it reaches an opacity of 0, and then I remove it so only the lines that need to be animated are left:
private void drawLinesInvalid() {
Iterator<int[]> iterator = invalidLines.iterator();
// Loop through each element in the Queue, delete it from the bitmap with the porter
// duff mode to keep the transparancy of the layer. Then draw line with the given opacity
while (iterator.hasNext()) {
int[] invalidLine = iterator.next();
float[] line = {invalidLine[1], invalidLine[2], invalidLine[3], invalidLine[4]};
Xfermode originalXfermode = paint.getXfermode();
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
mCanvas.drawLines(line, paint);
paint.setXfermode(originalXfermode);
paint.setColor(Color.RED);
paint.setAlpha(invalidLine[0]);
mCanvas.drawLines(line, paint);
}
}
// Call this function in the onTouch method
private void addLineToInvalidList(float[] line) {
// Store each line a queue with its current opacity
int[] lineWithOpacity = new int[5];
lineWithOpacity[0] = 250;
lineWithOpacity[1] = (int) line[0];
lineWithOpacity[2] = (int) line[1];
lineWithOpacity[3] = (int) line[2];
lineWithOpacity[4] = (int) line[3];
invalidLines.add(lineWithOpacity);
}
private void decreaseLineOpacity() {
Iterator<int[]> iterator = invalidLines.iterator();
// Remove all lines that are finished animating (opacity = 0)
while (iterator.hasNext()) {
int[] line = iterator.next();
if (line[0] == 0) {
iterator.remove();
}
}
// Decrease opacity on lines that are left
iterator = invalidLines.iterator();
while (iterator.hasNext()) {
int[] line = iterator.next();
line[0] -= 10;
}
}
Upvotes: 0
Views: 2707
Reputation: 5151
Considering you are drawing all three bitmaps on the same view, using an AlphaAnimation
may be a bit tricky.
I would suggest spawning a thread that changes the alpha value of the invalid red line(s) bitmap over time (sleeping for set intervals with Thread.sleep
). However, for this to perform well you should look into using a SurfaceView
as calling postInvalidate
multiple times may be quite costly (unless this is running on Android 3.0+ with hardware acceleration).
Upvotes: 1