Aggressor
Aggressor

Reputation: 13551

Apply ImageView as Mask To Another ImageView

I have read the posts on applying an .png as an ImageView mask (Android how to apply mask on ImageView?) but Im curious if it can be done without having a .png file.

I have an ImageView that takes up the whole screen. What I want to is to mask a square in the middle of it. However I don't want to use an actual .png file and use that as a mask. I want to 'draw' the square by making an ImageView of the appropriate size and then using that ImageView as the mask.

Is this possible?

Upvotes: 0

Views: 887

Answers (3)

Aggressor
Aggressor

Reputation: 13551

Thanks for the help.

I thought I'd share my exact solution as my goal was to create a bitmap that takes up the full screen and has a square cutout in the top area.

This code does the trick:

private void createMask()
{
    int dimension = 300;
    ImageView mask = new ImageView(_activity);

    //Create the square to serve as the mask
    Bitmap squareMask = Bitmap.createBitmap(dimension,dimension, Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(squareMask);
    Paint black = new Paint();
    black.setStyle(Paint.Style.FILL);
    black.setColor(Color.BLACK);
    canvas.drawRect(0.0f,0.0f,(float)dimension,(float)dimension,black);

    //create the darkness bitmap
    Bitmap darknessView = Bitmap.createBitmap((int)screenWidthPX(),(int)screenHeightPX(), Bitmap.Config.ARGB_8888);
    canvas = new Canvas(darknessView);
    black.setStyle(Paint.Style.FILL);
    black.setColor(Color.BLACK);
    canvas.drawRect(0.0f,0.0f,(int)screenWidthPX(),(int)screenHeightPX(),black);

    //create the masked version of the darknessView
    Bitmap darknessViewMasked = Bitmap.createBitmap((int)screenWidthPX(),(int)screenHeightPX(), Bitmap.Config.ARGB_8888);
    canvas = new Canvas(darknessViewMasked);
    Paint paint = new Paint();
    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
    canvas.drawBitmap(darknessView,0,0,null);
    canvas.drawBitmap(squareMask,0,0,paint);
    paint.setXfermode(null);
    _darknessView.setImageBitmap(darknessViewMasked);
    root.addView(_darknessView);
}

Upvotes: 0

kris larson
kris larson

Reputation: 30985

Yes, this is possible.

In the answer you referenced, you see how they set up a Paint to do the masking then called

canvas.drawBitmap(mMask, 0, 0, maskPaint);

There's no reason you can't do the same thing with

canvas.drawRoundRect(left, top, right, bottom, radius, radius, maskPaint);

Upvotes: 1

roarster
roarster

Reputation: 4086

Couldn't you just draw a circular gradient instead of the png's bitmap? I've grabbed makeRadGrad and you could just use it as your bitmap in the answer you linked:

private Bitmap mImage = ...;
private Bitmap mMask = ...;  // png mask with transparency
private int mPosX = 0;
private int mPosY = 0;

private final Paint maskPaint;
private final Paint imagePaint;

public CustomView (final Context context) {
    maskPaint = new Paint();
    maskPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));

    imagePaint = new Paint();
    imagePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OVER));

    mImage = //set image
    mMask = makeRadGrad(mImage.width()); //we'll just assume you have a perfectly square image

}

/* TODO
if you have more constructors, make sure you initialize maskPaint and imagePaint
Declaring these as final means that all your constructors have to initialize them.
Failure to do so = your code won't compile.
*/

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

    canvas.save();
    canvas.drawBitmap(mMask, 0, 0, maskPaint);
    canvas.drawBitmap(mImage, mPosX, mPosY, imagePaint);
    canvas.restore();
}

private Bitmap makeRadGrad(int size) {
    int radius = (int) (size/2f);
    RadialGradient gradient = new RadialGradient(radius, radius, radius, 0xFF00FF00,
        0x00000000, android.graphics.Shader.TileMode.CLAMP);
    Paint p = new Paint();
    p.setDither(true);
    p.setShader(gradient);

    Bitmap bitmap = Bitmap.createBitmap(size, size, Config.ARGB_8888);
    Canvas c = new Canvas(bitmap);
    c.drawCircle(radius, radius, radius, p);

    return bitmap;
}

Upvotes: 1

Related Questions