0

So I've been struggling with this for a better part of a day. Suppose I have a custom ImageView that I want to overlay over a background View (both within a RelativeLayout), which when touched, it erases portions of the View's source bitmap like an erase tool in MS Paint, exposing the View below it. I've checked pretty much all of the threads (like this one) and they suggest to use PorterDuff SRC Mode in the Paint object as well as creating a Canvas out out the ARGB_8888 shadow copy of the source bitmap to apply the masking.

Also, I can't set the source of the overlay ahead of time since I have to download it over the network so that the ImageView's scale type takes care of the scaling for me.

Every time I override onDraw, when I apply the erase on the IV's Bitmap, it unveils a black background instead of the view below it, even though I set the background to transparent. So I'm at my last rope as to what to do in order to unveil the background view.

Here's what I have so far:

view constructor:

    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));  
    paint.setColor(Color.TRANSPARENT);
    paint.setStyle(Paint.Style.STROKE);
    paint.setStrokeJoin(Paint.Join.ROUND);
    paint.setStrokeWidth(STROKE_WIDTH);
    paint.setAntiAlias(true);

overrode setImageBitmap to set my canvas from my re-configed source bitmap:

public void setImageBitmap(Bitmap bitmap){
    super.setImageBitmap(bitmap);
    Drawable bd = getDrawable();
    if(bd == null){
        return;
    }

    Bitmap fullSizeBitmap = ((BitmapDrawable) bd).getBitmap();
    overlay = fullSizeBitmap.copy(Config.ARGB_8888, true);
    c2 = new Canvas(overlay);
}

onDraw method:

protected void onDraw(Canvas canvas) {
    /*
     * Override paint call by re-drawing the view's Bitmap first, then overlaying our path on top of it
     */
    Drawable bd = getDrawable();
    if(bd == null){
        return;
    }
    Bitmap fullSizeBitmap = ((BitmapDrawable) bd).getBitmap();
    if(fullSizeBitmap != null && c2 != null){
        canvas.drawColor(Color.TRANSPARENT);
        c2.drawBitmap(fullSizeBitmap, 0, 0, null);
        c2.drawPath(path, paint);
        canvas.drawBitmap(overlay, 0, 0, null);
    }
}
Community
  • 1
  • 1
Diego Tori
  • 399
  • 5
  • 19
  • This probably isn't the best way to do it, but it is an idea. On the ImageView that you want to make transparent, you could just set a transparent .png image to the background instead of doing canvas drawing. Meaning, you'd make a tiny .png image and package within your app. – Reed Nov 22 '11 at 00:22
  • Well, I already have such image within my resources, but I dunno what benefit that has over a) setting the IV's background to null or b) setting it's color and canvas to transparent? I'll give it a shot though. – Diego Tori Nov 22 '11 at 00:26
  • Nope, even setting a transparent PNG as the background didn't make a difference :-( – Diego Tori Nov 22 '11 at 00:44
  • You could use `addView` to add the image that will later be removed and then call `removeView` on touch. I guess that may or may not work depending on what you actually want your app to do. And I don't see any errors in your code, but my guess is that there's something silly that's destroying the whole operation. Usually my unexplainable errors are due to my carelessness. I may be wrong, but it may be something really simple. – Reed Nov 22 '11 at 00:47
  • What if you spoofed the effect entirely? Create a View which contains both the top image (set to visible) and the bottom view components (set to be invisible). When the top image is clicked, make it invisible and make the other view components visible. – Adil B Nov 22 '11 at 00:49
  • That's not what I'm looking for. I need to be able to make transparent parts of the ImageView depending on where the user drags his finger. – Diego Tori Nov 22 '11 at 00:52

1 Answers1

1

I know this is a really old question but here is what I did to fix a similar problem I had. Maybe it helps someone in the future.

From API level 11 and up you have to specify this piece of code for your ImageView to unveil the image in the back and not a black area.

if (Build.VERSION.SDK_INT >= 11) {
    imageview.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}

This helped me displaying the back image successfully

the-ginger-geek
  • 7,041
  • 4
  • 27
  • 45
  • but what about the api < 11 – Kapil Vats Mar 04 '13 at 10:39
  • This will not be needed for the older api levels – the-ginger-geek Mar 04 '13 at 11:48
  • but then why I am getting black line for older api but my code works well on android 4.1, here is my question http://stackoverflow.com/questions/15200187/paint-xfermode-draws-black-line-on-andorid-2-2 – Kapil Vats Mar 04 '13 at 11:49
  • That piece of code disables hardware acceleration for the specific view (android api 11+). Look at this (http://stackoverflow.com/questions/6792115/detect-hardware-acceleration-at-runtime-android) link and see if that helps. If not you will probably have to disable hardware acceleration in the manifest not quite figured that one out yet. – the-ginger-geek Mar 04 '13 at 11:57
  • You can also have a look at the developer docs for more info http://developer.android.com/guide/topics/graphics/hardware-accel.html – the-ginger-geek Mar 04 '13 at 12:05
  • thanks Neil, but am disabling the hardware-accel in mainfest only even than its not working – Kapil Vats Mar 04 '13 at 12:08