Android - Fade out bitmap image on canvas

Raj picture Raj · Aug 14, 2013 · Viewed 12.2k times · Source

I am drawing a scaled bitmap onto a canvas and would like to fade my image out at a specified time.

Basically, when my character image goes over a certain section of the canvas, I require the character image to slowly fade away (3 seconds), before the page automatically re-directs to the next java class.

Currently, my image simply redirects to the new java class, please see below some code to how I am creating my image.

Resources res = getResources();
float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20, res.getDisplayMetrics());
imgSpacing = (int) px / 2;
int size = (int) ((PhoneWidth / 5) - px);

chrImg = BitmapFactory.decodeResource(getResources(), R.drawable.character);
chrImg = Bitmap.createScaledBitmap(chrImg, size, size, true);

Then within the canvas onDraw:

if(indexX == mazeFinishX && indexY == mazeFinishY)
{
    canvas.drawBitmap(finish, j * totalCellWidth, i * totalCellHeight, null);
    // As soon as the character moves over this square they are automatically re-directed to new page
    // This is where I want to fade the character image out before the re-direct
}

I have looked online, however cannot quite work out how to get the fading to work for my drawable image fetched from my games resources drawable folder. Thanks

Answer

Dane White picture Dane White · Aug 21, 2013

If you think there's a possibility you will want to change the fade animation down the road, such as scaling and/or rotating, then you should go with an animation XML.

But for just a quick bitmap fade, you can repeatedly post delayed invalidation messages. You probably want to limit your invalidated area to just where your character bitmap is:

private static final int FADE_MILLISECONDS = 3000; // 3 second fade effect
private static final int FADE_STEP = 120;          // 120ms refresh

// Calculate our alpha step from our fade parameters
private static final int ALPHA_STEP = 255 / (FADE_MILLISECONDS / FADE_STEP);

// Initializes the alpha to 255
private Paint alphaPaint = new Paint();

// Need to keep track of the current alpha value
private int currentAlpha = 255;

@Override
protected void onDraw(Canvas canvas) {
    ...
    if(indexX == mazeFinishX && indexY == mazeFinishY) {

        // Drawing your wormhole?
        int x = j * totalCellWidth;
        int y = i * totalCellHeight;
        canvas.drawBitmap(finish, x, y, null);

        if (currentAlpha > 0) {

           // Draw your character at the current alpha value
           canvas.drawBitmap(chrImg, x, y, alphaPaint);

           // Update your alpha by a step
           alphaPaint.setAlpha(currentAlpha);
           currentAlpha -= ALPHA_STEP;

           // Assuming you hold on to the size from your createScaledBitmap call
           postInvalidateDelayed(FADE_STEP, x, y, x + size, y + size);

        } else {
           // No character draw, just reset your alpha paint
           currentAlpha = 255;
           alphaPaint.setAlpha(currentAlpha);

           // Now do your redirect
        }
    }
    ...
}

I'd recommend putting the constants FADE_MILLISECONDS and FADE_STEP into res/integers.xml just so they aren't hard-coded.