20

My idea is to overlap 2 images on top of each other and upon onTouch, the top image should be made transparent on that touched radius, thus exposing the bottom image.

This is how I overlay the 2 images:

        Bitmap bmOverlay = Bitmap.createBitmap(bmp1.getWidth(), bmp1.getHeight(), bmp1.getConfig());
        Canvas canvas = new Canvas(bmOverlay);
        canvas.drawBitmap(bmp1, new Matrix(), null);
        canvas.drawBitmap(bmp2, new Matrix(), null);

I have looked into this post and have a Paint like below to make it transparent:

        mPaint = new Paint();
        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
        mPaint.setColor(Color.TRANSPARENT);
        mPaint.setAntiAlias(true); 

public void onDraw(Canvas canvas) {
            canvas.drawCircle(40, 40, 30, mPaint); //hardcode to test
}

Problem is, I think the circle straight away make the 2 images transparent on the defined radius, how can I make only the top bitmap transparent?

Community
  • 1
  • 1
SteD
  • 13,909
  • 12
  • 65
  • 76

2 Answers2

36
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BlurMaskFilter.Blur;
import android.graphics.BitmapFactory;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;

public class StartActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new TouchView(this));


    }

    class TouchView extends View{
        Bitmap bgr;
        Bitmap overlayDefault;
        Bitmap overlay;
        Paint pTouch;
        int X = -100;
        int Y = -100;
        Canvas c2;

        public TouchView(Context context) {
            super(context);

            bgr = BitmapFactory.decodeResource(getResources(),R.drawable.bgr);
            overlayDefault = BitmapFactory.decodeResource(getResources(),R.drawable.over);
            overlay = BitmapFactory.decodeResource(getResources(),R.drawable.over).copy(Config.ARGB_8888, true);  
            c2 = new Canvas(overlay);

            pTouch = new Paint(Paint.ANTI_ALIAS_FLAG);         
            pTouch.setXfermode(new PorterDuffXfermode(Mode.SRC_OUT)); 
            pTouch.setColor(Color.TRANSPARENT);
            pTouch.setMaskFilter(new BlurMaskFilter(15, Blur.NORMAL));


        }

        @Override
        public boolean onTouchEvent(MotionEvent ev) {

            switch (ev.getAction()) {

                case MotionEvent.ACTION_DOWN: {

                    X = (int) ev.getX();
                    Y = (int) ev.getY();
                    invalidate();

                    break;
                }

                case MotionEvent.ACTION_MOVE: {

                        X = (int) ev.getX();
                        Y = (int) ev.getY();
                        invalidate();
                        break;

                }           

                case MotionEvent.ACTION_UP:

                    break;

            }
            return true;
        }


        @Override
        public void onDraw(Canvas canvas){
            super.onDraw(canvas);

            //draw background
            canvas.drawBitmap(bgr, 0, 0, null);
            //copy the default overlay into temporary overlay and punch a hole in it                          
            c2.drawBitmap(overlayDefault, 0, 0, null); //exclude this line to show all as you draw
            c2.drawCircle(X, Y, 80, pTouch);
            //draw the overlay over the background  
            canvas.drawBitmap(overlay, 0, 0, null);

        }


    }


}
Lumis
  • 21,517
  • 8
  • 63
  • 67
  • I tried to do it without using second canvas but could not get xfer mode working. Note that "overlay" is a mutable bitmap. – Lumis Mar 26 '11 at 00:08
  • 1
    You are welcome. It was an interesting problem and I was surprised that it was not as easy as I initially thought. It seems that xfer modes work as expected with a canvas derived from a bitmap, but not with the canvas which belongs to a View. That is why I used c2 – Lumis Mar 27 '11 at 19:51
  • @Lumins i need to take the exact pixel of first image and place it in second image.so the second image will look like the some part of first image. how to do using xFerMode? – deepa Jul 22 '11 at 05:03
  • @deepa check this link about setting individual pixels http://stackoverflow.com/questions/5155999/android-make-specific-green-color-in-background-image-transparent/5156808#5156808 – Lumis Jul 22 '11 at 09:31
  • 1
    Works perfectly on Android 4.x But on 2.x the circles are black instead of showing the image behind. Any idea? – User Apr 20 '13 at 13:53
  • @lxx - actually I developed this on 2.2 long time ago. Also I work a lot with 2D graphics and have not seen a difference between 2.2, 2.3 and 4.x, so it must be something with your particular device. It looks like Xfermode fails, try Mode.CLEAR – Lumis Apr 20 '13 at 20:09
  • 1
    @Lumins I am trying to work with your code , I am getting black circle only I am working on Android 4.1.2, Kindly help me where might i go wrong. I have used both Mode.CLEAR and Mode.SRC_OUT but only black image is drawing nothing is made transparent – Ranjith Jun 26 '13 at 01:28
  • @Lumis this is the exact fucntionality i am trying to implement from long, but the thing is i have 2 imageViews one on top the other and i want to show the behind imageview on touch int that area , so any pointers how to implement the same for imageviews rather than using canvas onDraw? – user2229100 Aug 13 '14 at 11:32
0

Heh, you've got the answer right inside your post!

Basically try something like:

public void onDraw(Canvas canvas) {    
    if (myPaintFlag) {
        canvas.drawBitmap(bmp1, new Matrix(), null);
        canvas.drawBitmap(bmp2, new Matrix(), mPaint);
    }
    else {
        canvas.drawBitmap(bmp1, new Matrix(), mPaint);
        canvas.drawBitmap(bmp2, new Matrix(), null);
    }   
}
user432209
  • 20,007
  • 10
  • 56
  • 75
  • I tried to use mPaint to draw the bitmap, but it will make the whole screen becomes only black color. My guess is it's making the whole bitmap transparent this way? – SteD Mar 20 '11 at 14:04
  • That could be. Try changing the draw order. – user432209 Mar 20 '11 at 18:31