13

i'm attempting to change the background image of a custom View with some success. the image will change but the problem is that i still see traces of the old image. when i attempt to clear the canvas before drawing the new image, it doesn't appear to work. i create a bitmap to store the image. when changing the image, i call Canvas.drawColor() before drawing the new image but the old image persists. i've tried drawColor(0), drawColor(Color.BLACK), c.drawColor(0, PorterDuff.Mode.CLEAR), and none of the above works. as such, i had to post this for review from more experienced minds than mine.

the actual code is as follows:

private int bgnd;
private boolean switching;

public void setBgnd(int incoming){
    switching = true;
    switch (incoming){

    case R.drawable.image1:
        bgnd = incoming;
        this.invalidate();
        break;

    case R.drawable.image2:
        bgnd = incoming;
        this.invalidate();
        break;

    }
}



protected void onDraw(Canvas c){
    if(switching == true){
        Bitmap b = BitmapFactory.decodeResource(getResources(), bgnd);
        c.drawColor(0, PorterDuff.Mode.CLEAR);
        c.drawBitmap(b, 0, 0, null);
        switching = false;

    }else{
        Bitmap b = BitmapFactory.decodeResource(getResources(), bgnd);
        c.drawBitmap(b, 0, 0, null);
    }
}
Prmths
  • 2,022
  • 4
  • 21
  • 38

4 Answers4

31

Just like you, I struggled how to clear a top layer/surfaceview in my multiple layer/surfaceview app. After 2 days searching and coding, I found out my own way and this is how I cleared a canvas before drawing, you can use it when having multiple layers/surfaceviews. The background layer will not be covered with black, that is the trick.

Paint paint = new Paint();
paint.setXfermode(new PorterDuffXfermode(Mode.CLEAR));
canvas.drawPaint(paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC));
// start your own drawing
longdooooo
  • 326
  • 3
  • 2
  • 1
    I think it would have taken me more than 2 days to figure this one out vs. the 2 minutes it took me to get here. Thx strangeInAStrangerLand + longdooooo – Mark Lapasa Jan 25 '12 at 22:55
3

You can use Canvas's method drawRGB.

Baz
  • 36,440
  • 11
  • 68
  • 94
ojs
  • 31
  • 1
  • drawRGB() does not clear the alpha channel and the bitmap will become opaque, hence it can only be used if the bitmap is the only layer or the background layer. There is also a method drawARGB(), which allows treating the alpha channel as well. Haven't tried if it works, though. – Oliver Hausler Nov 25 '14 at 17:59
  • 1
    Note that drawRGB just uses `drawColor(Color.rgb(r, g, b))` – TameHog Apr 10 '15 at 19:08
2

Do you not need to also call invalidate() from within your onDraw method, so that changes made in that onDraw are updated on the screen?

The invalidate() in your switch will invoke your onDraw after you call setBgnd, but there's nothing saying to redraw after you've made changes to the Canvas.

C0deAttack
  • 24,419
  • 18
  • 73
  • 81
  • 1
    i'm under the impression that calling invalidate() will tell a view to call onDraw() and draw its self. that being the case putting that call in the method would cause it to loop forever, as seen in the example at: http://www.anddev.org/basic_and_simple_2d_drawing_-_animation-t3085.html – Prmths Jan 10 '11 at 19:55
  • Ah you're right, had to go look it up, http://developer.android.com/guide/topics/graphics/index.html. Sorry my understanding wasn't correct. – C0deAttack Jan 10 '11 at 20:08
  • I thought that in the beginning, too. The question to me is, if invalidate() tells a view to redraw itself, why doesn't this view completely redraw itself until it's moved later in an animation? the bottom half of the object looks right but the other half is still the old surface. – Prmths Jan 12 '11 at 18:32
  • i've also tried using an 8 bit image as i've read that it's possible that the issue is caused by difficulties android has with 32 bit images. i didn't think that was the case and i did find that it wasn't helpful. i also tried setBackgroundResource() (actually what i tried first even before bothering with a canvas) but it also doesn't work, even when called from inside onDraw(). – Prmths Jan 13 '11 at 18:42
0

I just meet this problem.

I solve it by repeating “..Drawxxx();Post();” for at least 3 times,it works well.

I guess ,“double buffering” is the reason,sometimes it is “trible buffering”.we need to repeat our drawing to make sure that each “buffer” is updated..

ohzso
  • 1