Android UI: Creating a layout rounded only in the top

Sadesh
2 min readFeb 10, 2018

--

If you want to make a rounded layout like below, it will be pretty simple to create it with CardView.

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="24dp">

<android.support.v7.widget.CardView
android:id="@+id/parent_layout"
android:layout_width="match_parent"
android:layout_height="400dp"
android:layout_margin="16dp"
app:cardCornerRadius="8dp">

<ImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="@drawable/kitty" />

</android.support.v7.widget.CardView>

</FrameLayout>

There is another way to do the same too.

But this works only from Lollipop onwards.

From Lollipop onwards, you can clip any View to its outline. What that means is if you set a background to be a rounded shape for any View, then the View will be clipped to be rounded like in the image shared above.

<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="8dp" />
</shape>

And use this shape in layout xml,

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="24dp">

<ImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="400dp"
android:layout_margin="16dp"
android:background="@drawable/bg_rounded"
android:scaleType="centerCrop"
android:src="@drawable/kitty" />

</FrameLayout>

To do the actual clipping, Android introduced a property called android:clipToOutline. But due to a bug, this property is not recognized and will throw a compiler error if you use it in xml. No worries, still you can call image.setClipToOutline(true) from Java/Kotlin code.

Please note that if you want to round the corners of an ImageView with setClipToOutline(), your image must come from android:src instead of android:background (since background is used for the rounded shape). If you must use background to set your image instead of src, you can wrap this ImageView inside another layout and call setClipToOutline()on that layout.

But only rectangle, circle and rounded rectangle shapes are supported according to the documentation. I didn’t check the circle though. Even with the rounded rectangle, it works only if all corners are rounded like the xml shared above.

It doesn’t work if you want to round only the top corners like this,

<shape xmlns:android="http://schemas.android.com/apk/res/android">

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

</shape>

So, how to create a layout like this,

For this one, you can remove the background shape from ImageView and set only the top corners to be rounded from Java/Kotlin code like this,

val image = findViewById<ImageView>(R.id.image)
val curveRadius = 20F

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

image.outlineProvider = object : ViewOutlineProvider() {

@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
override fun getOutline(view: View?, outline: Outline?) {
outline?.setRoundRect(0, 0, view!!.width, (view.height+curveRadius).toInt(), curveRadius)
}
}

image.clipToOutline = true

}

The above example uses ImageView. But, the same will work for all Views and ViewGroups.

Happy coding!

--

--

Sadesh

Android Engineer, Occasional Digital Nomad, Noob Dad, History Buff, Wanderlust