Draw Rectagle with fill outside bounds

2019-06-01 09:35发布

问题:

I am drawing an Rectangle with outside of rectangle fill. I tried some of this. But cant get the perfect one what i expected.

This is what i expected.

I tried

    Point pTopLeft = new Point();
    Point pBotRight = new Point();
    pTopLeft.x = 100;
    pTopLeft.y = 100;
    pBotRight.x = canvas.getWidth() - 100;
    pBotRight.y = canvas.getHeight() - 100;
    Rect above = new Rect(0, 0, canvas.getWidth(), pTopLeft.y);
    paint.setColor(Color.parseColor("#77000000"));
    canvas.drawRect(above, paint);
    Rect left = new Rect(0, pTopLeft.y, pTopLeft.x, pBotRight.y);
    paint.setColor(Color.parseColor("#77000000"));

    canvas.drawRect(left, paint);
    Rect right = new Rect(pBotRight.x, pTopLeft.y, canvas.getWidth(),
            pBotRight.y);
    paint.setColor(Color.parseColor("#77000000"));
    canvas.drawRect(right, paint);
    Rect bottom = new Rect(0, pBotRight.y, canvas.getWidth(),
            canvas.getHeight());

    paint.setColor(Color.parseColor("#77000000"));
    Paint paint_text = new Paint();
    paint_text.setColor(Color.WHITE);
    paint_text.setTextSize(50);
    paint_text.setTextAlign(Align.CENTER);

    canvas.drawText("Position Card in this Frame", canvas.getWidth() / 2,
            canvas.getHeight() - 30, paint_text);
    canvas.drawRect(bottom, paint);

And got like this

But i want to draw the rectangle and fill outside the bounds to achieve the rounded border. How can i do it?

EDIT When i tries to draw the rectangle one over one. The layout is like this..

That i cant give Color.TRANSPARENT for the center rectangle which fully tranparents the second rectangle..

回答1:

I'm still not entirely sure what you're trying to accomplish. The shape you show can be drawn as follows:

// set up some constants
int w = canvas.getWidth();
int h = canvas.getHeight();
RectF rect = new RectF(100, 100, w - 100, h - 100);
float radius = 10.0f; // should be retrieved from resources and defined as dp
float borderWidth = 2.0f; // ditto
int innerRectFillColor = 0x33000000; // or whatever shade it should be

// first fill the interior
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(innerRectFillColor);
paint.setStyle(Paint.Style.FILL);
canvas.drawRoundRect(rect, radius, radius, paint);
// then draw the border
paint.setColor(Color.WHITE);
paint.setStrokeWidth(borderWidth);
paint.setStyle(Paint.Style.STROKE);
canvas.drawRoundRect(rect, radius, radius, paint);

If instead you want to draw around a hole (so the background shows through), the trick of drawing the surrounding rectangles won't work because of the rounded corners (the border also makes it more complicated). Instead, you can create a separate Bitmap that has a transparent hole and then draw that. You'll need to use a Porter-Duff transfer mode of CLEAR to punch the hole in the bitmap:

// same constants as above except innerRectFillColor is not used. Instead:
int outerFillColor = 0x77000000;

// first create an off-screen bitmap and its canvas
Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas auxCanvas = new Canvas(bitmap);

// then fill the bitmap with the desired outside color
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(outerFillColor);
paint.setStyle(Paint.Style.FILL);
auxCanvas.drawPaint(paint);

// then punch a transparent hole in the shape of the rect
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
auxCanvas.drawRoundRect(rect, radius, radius, paint);

// then draw the white rect border (being sure to get rid of the xfer mode!)
paint.setXfermode(null);
paint.setColor(Color.WHITE);
paint.setStyle(Paint.Style.STROKE);
auxCanvas.drawRoundRect(rect, radius, radius, paint);

// finally, draw the whole thing to the original canvas
canvas.drawBitmap(bitmap, 0, 0, paint);


回答2:

Here's how I punched out a rounded rectangle window from my background. You're actually drawing four rectangles around a center window, then filling that window with a RoundRectShape that has an outer radius of 0 and thin inset with rounded edges.

    Rect frame = new Rect(left, top, right, bottom); // Window location on screen
    int width = canvas.getWidth();
    int height = canvas.getHeight();


    paint.setColor(maskColor); // Make sure your mask is semi-transparent

    // Draw four bounding rectangles  
    canvas.drawRect(0, 0, width, frame.top, paint); 
    canvas.drawRect(0, frame.top, frame.left, frame.bottom + 1, paint);  
    canvas.drawRect(frame.right + 1, frame.top, width, frame.bottom + 1, paint);
    canvas.drawRect(0, frame.bottom + 1, width, height, paint);

    // Create rounded rectangle to fill window 
    float outerRadii[] = {0, 0, 0, 0, 0, 0, 0, 0}; // The outside edge is just a rectangle
    float innerRadii[] = {8, 8, 8, 8, 8, 8, 8, 8}; // The inside edge is rounded
    RoundRectShape roundRect = new RoundRectShape(outerRadii, new RectF(5,5,5,5), innerRadii); // We'll stick this shape into the frame we made

    roundRect.resize(frame.width()+1, frame.height()+1); // Adjust size to match the punched-out frame 
    canvas.save();
    canvas.translate(frame.left, frame.top); // The RoundRectShape draws to the canvas at (0,0), so we need to offset the canvas, draw, then restore
    roundRect.draw(canvas, paint);
    canvas.restore();

And here's the result:

http://i.stack.imgur.com/4qdTw.png