with - android shape ring




How can I create a rectangle with two curved sides in XML drawable? (7)

Define the height and make the radius half of the height.

I want the left and right sides (not the corners) of the rectangle to be curved. Or say the top and bottom sides of an oval shape straight.

How can I achieve something like this?


I arrive a bit late, and the answer must not be totally complete (i dont consider flexible heights), but at least if we know in advance the height in dp the trick is to have the radius as the half of the height of the button. For instance if the height would be 48dp, we could do something like:

<?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="24dp" />
</shape>

It seems that the maximum radius allowed in the shape is half of the total height in the shape bellow, so you can use it to have a shape with flexible height that keep the desire ratio:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="rectangle">
    <solid android:color="#ffffff" />
    <size android:height="@dimen/height" />
    <corners
        android:radius="@dimen/height"
        />
</shape>

It's worked fine!

<?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="rectangle">

    <solid
        android:color="@color/color_red"/>
    <corners
        android:radius="10000dp" /> 
</shape>

To make the sides always stay curvy with any height, I end up have to create the shape programmatically like below (code in Kotlin)

class CurvedSidesShape : RectShape() {
    override fun draw(canvas: Canvas, paint: Paint?) {
        var path = Path()
        path.addRoundRect(rect(), rect().height(), rect().height(), Path.Direction.CW)
        canvas.drawPath(path, paint)
    }
}

and here's how I use the shape as a button background

class CurvedSidesButton : Button {
    private var mHeight: Int = 0

    constructor(context: Context?) : super(context) {
        init(context, null, 0, 0)
    }

    .
    .
    .

    override fun draw(canvas: Canvas?) {
        setCurvedSidesBackground(height)
        super.draw(canvas)
    }

    private fun setCurvedSidesBackground(height: Int) {
        if (height != mHeight) {
            val curvedSidesShape = ShapeDrawable(CurvedSidesShape())
            curvedSidesShape.intrinsicWidth = width
            curvedSidesShape.intrinsicHeight = height
            curvedSidesShape.paint.color = Color.RED
            background = curvedSidesShape
            mHeight = height
        }
    }
}

Try setting the border radius to half of the height. In CSS, border-radius:50% creates an ellipse, so I would guess that if it's only 50% of the height then you would get something like that.


You can increase the radius size to 200dp and set the drawable to textview's background

<solid android:color="#E6121A" />

<corners
    android:bottomLeftRadius="12dp"
    android:bottomRightRadius="12dp"
    android:topLeftRadius="12dp"
    android:topRightRadius="12dp" />





shapedrawable