How to make a rectangle with inverted rounded corners?
Asked Answered
C

4

11

I know how to make rectangle with rounded corners, like this

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid
        android:color="#FF0000"/>
    <corners
        android:radius="10000dp" />
</shape>

It looks like this:

enter image description here

But I want to make the inverse of that (center transparent and sides filled with color), which should look like this:

enter image description here

Thanks

Chaeta answered 6/12, 2018 at 8:1 Comment(4)
why don't you, set a background to red and change the circle color to white.Tingly
@SathyaBaman Maybe, because white != transparentLachrymator
agreed...................Tingly
it looks impossible with XML for mePictograph
V
11

Not proper way, but will get the result, try

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="rectangle">
            <padding
                android:bottom="-100dp"
                android:left="-100dp"
                android:right="-100dp"
                android:top="-100dp" />
        </shape>
    </item>
    <item>
        <shape android:shape="rectangle">
            <corners android:radius="200dp" />
            <stroke
                android:width="100dp"
                android:color="#FF0000" />
        </shape>
    </item>
</layer-list>
Vaud answered 6/12, 2018 at 8:30 Comment(3)
Mind to explain how would this drawable produce a transparent capsule surrounded by a pinkish frame?Lachrymator
The trick is in the minus padding and corner radius, you can adjust these values for deserved resultVaud
Do mind that if you use this method, and apply a tint/filter to your drawable, you will loose your frameAtmolysis
S
3

Based on: https://mcmap.net/q/616553/-how-to-create-a-39-transparent-circle-inside-rectangle-39-shape-in-xml-in-android

Try with custom view:

public class CustomView extends View {
private Path mPath = new Path();

public CustomView(Context context) {
    super(context);
}

public CustomView(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
}


@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    mPath.reset();
    mPath.addRoundRect(0, 0, getWidth(), getHeight(), 1000, 1000, Path.Direction.CW);
    mPath.setFillType(Path.FillType.INVERSE_EVEN_ODD);
    canvas.clipPath(mPath);
    canvas.drawColor(Color.parseColor("#FF0000"));
}
}

enter image description here

Slapup answered 6/12, 2018 at 8:26 Comment(0)
F
0

Check this

    <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:left="5dp"
        android:top="5dp"
        android:right="5dp"
        android:bottom="5dp">
        <shape xmlns:android="http://schemas.android.com/apk/res/android"
            android:shape="rectangle">
            <solid
                android:color="#FF0000"/>
        </shape>
    </item>
    <item
        android:left="5dp"
        android:top="5dp"
        android:right="5dp"
        android:bottom="5dp">
        <shape xmlns:android="http://schemas.android.com/apk/res/android"
            android:shape="rectangle">
            <solid
                android:color="#FFFFFF"/>
            <corners
                android:radius="10000dp" />
        </shape>
    </item>
</layer-list>
Ferrol answered 6/12, 2018 at 8:19 Comment(1)
What is needed is a transparent center - this is just white and would cover everything.Comedic
E
0

I needed this as well so I created following Drawable class. To get the solution that is wanted for this question you can use it like following:

val radius = min(view.width, view.height)
val bg = InvertedRectDrawable(Color.RED, radius, 0)
view.background = bg

Code

import android.graphics.*
import android.graphics.drawable.Drawable

class InvertedRectDrawable(
    private val color: Int,
    private val cornerRadius: Int,
    private val border: Int,
    private val contentColor: Int? = null
) : Drawable() {

    private var paint: Paint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
        this.color = [email protected]
    }
    private var paint2: Paint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
        contentColor?.let {
            this.color = it
        }
    }
    private val path = Path()

    override fun draw(canvas: Canvas) {
        path.reset()
        path.addRoundRect(
            border.toFloat(),
            border.toFloat(),
            bounds.width().toFloat() - 2 * border.toFloat(),
            bounds.height().toFloat() - 2 * border.toFloat(),
            cornerRadius.toFloat(),
            cornerRadius.toFloat(),
            Path.Direction.CW
        )
        path.fillType = Path.FillType.INVERSE_EVEN_ODD

        val s = canvas.save()
        canvas.clipPath(path)
        canvas.drawPaint(paint)

        contentColor?.let {

            canvas.restoreToCount(s)

            path.fillType = Path.FillType.EVEN_ODD
            canvas.clipPath(path)
            canvas.drawPaint(paint2)
        }
    }

    override fun setAlpha(alpha: Int) {
        paint.alpha = alpha
    }

    override fun setColorFilter(colorFilter: ColorFilter?) {
        paint.colorFilter = colorFilter
    }

    override fun getOpacity(): Int {
        return PixelFormat.TRANSLUCENT
    }
}
Erastes answered 10/11, 2020 at 8:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.