Exploring Shapes in Android Jetpack Compose

Jetpack Compose Shapes

In this article, we’ll explore shapes in Android Jetpack Compose with the help of examples.

Prerequisites:

First, create an empty Jetpack Compose project and open MainActivity. Add a composable called MyUI() and call it from the onCreate() method. We will write our code in it.

MainActivity for the Material 3 Jetpack Compose:

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.CornerSize
import androidx.compose.foundation.shape.CutCornerShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.unit.dp
import com.example.yourprojectname.ui.theme.YourProjectNameTheme

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            YourProjectNameTheme {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    Column(
                        modifier = Modifier.fillMaxSize(),
                        verticalArrangement = Arrangement.Center,
                        horizontalAlignment = Alignment.CenterHorizontally
                    ) {
                        MyUI()
                    }
                }
            }
        }
    }
}

@Composable
fun MyUI() {

}

MainActivity for the Material 2 version:

// we need the following packages
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.CornerSize
import androidx.compose.foundation.shape.CutCornerShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.unit.dp

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            YourProjectNameTheme(darkTheme = false) {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colors.background
                ) {
                    Column(
                        modifier = Modifier.fillMaxSize(),
                        verticalArrangement = Arrangement.Center,
                        horizontalAlignment = Alignment.CenterHorizontally
                    ) {
                        MyUI()
                    }
                }
            }
        }
    }
}

@Composable
fun MyUI() {
  
}

Jetpack Compose offers multiple shapes out of the box. They are:

  1. RoundedCornerShape
  2. CutCornerShape
  3. RectangleShape
  4. CircleShape

1. RoundedCornerShape:

It creates a rectangle with rounded corners.

For this article, let’s play with the Box(). We can set the box shape using the modifier’s clip() function.

@Composable
fun MyUI() {
    Box(
        modifier = Modifier
            .size(size = 100.dp)
            .clip(shape = RoundedCornerShape(size = 12.dp))
            .background(color = Color.Green)
    ) {
    }
}

Output:

RoundedCornerShape

The method provides different overloads:

#1 fun RoundedCornerShape(size: Dp)

This is what we have done above. We have set the size in Dp.

#2 fun RoundedCornerShape(size: Float)

It takes float instead of Dp.

@Composable
fun MyUI() {
    Box(
        modifier = Modifier
            .size(size = 100.dp)
            .clip(shape = RoundedCornerShape(size = 30f))
            .background(color = Color.Green)
    ) {
    }
}

Output:

jetpack compose rounded corners
#3 fun RoundedCornerShape(percent: Int)

We can set the corner radius in terms of percentage. If we pass 50, we get a circle.

@Composable
fun MyUI() {
    Box(
        modifier = Modifier
            .size(size = 100.dp)
            .clip(shape = RoundedCornerShape(percent = 50))
            .background(color = Color.Green)
    ) {
    }
}

Output:

Circle 50 percent
#4 fun RoundedCornerShape(corner: CornerSize)

It takes the CornerSize object and creates a rounded rectangle. The object can be obtained from CornerSize() function. The function has multiple formats:

fun CornerSize(size: Dp): CornerSize
fun CornerSize(size: Float): CornerSize
fun CornerSize(percent: Int): CornerSize

Example:

@Composable
fun MyUI() {
    Box(
        modifier = Modifier
            .size(size = 100.dp)
            .clip(shape = RoundedCornerShape(corner = CornerSize(size = 30f)))
            .background(color = Color.Green)
    ) {
    }
}

Output:

jetpack compose rounded corners
#5 fun RoundedCornerShape(topStart: Dp = 0.dp, topEnd: Dp = 0.dp, bottomEnd: Dp = 0.dp, bottomStart: Dp = 0.dp)

We can control the size of the individual corners like top, bottom, left and right.

@Composable
fun MyUI() {
    Box(
        modifier = Modifier
            .size(size = 100.dp)
            .clip(
                shape = RoundedCornerShape(
                    topStart = 10.dp,
                    topEnd = 20.dp,
                    bottomEnd = 30.dp,
                    bottomStart = 40.dp
                )
            )
            .background(color = Color.Green)
    ) {
    }
}

Output:

RoundedCornerShape individual corners

Instead of Dp, it also accepts Float and Int (percentage):

fun RoundedCornerShape(topStart: Float = 0.0f, topEnd: Float = 0.0f, bottomEnd: Float = 0.0f, bottomStart: Float = 0.0f)
fun RoundedCornerShape(topStartPercent: Int = 0, topEndPercent: Int = 0, bottomEndPercent: Int = 0, bottomStartPercent: Int = 0)

Look at these beautiful buttons created using the above method.

2. CutCornerShape:

We can create a rectangle with cut corners.

@Composable
fun MyUI() {
    Box(
        modifier = Modifier
            .size(size = 100.dp)
            .clip(shape = CutCornerShape(size = 20.dp))
            .background(color = Color.Green)
    ) {
    }
}

Output:

CutCornerShape

Similar to RoundedCornerShape(), CutCornerShape() has multiple formats:

#1 fun CutCornerShape(size: Dp)
#2 fun CutCornerShape(size: Float)
#3 fun CutCornerShape(percent: Int)
#4 fun CutCornerShape(corner: CornerSize)
#5 fun CutCornerShape(topStart: Dp = 0.dp, topEnd: Dp = 0.dp, bottomEnd: Dp = 0.dp, bottomStart: Dp = 0.dp)
#6 fun CutCornerShape(topStart: Float = 0.0f, topEnd: Float = 0.0f, bottomEnd: Float = 0.0f, bottomStart: Float = 0.0f)
#7 fun CutCornerShape(topStartPercent: Int = 0, topEndPercent: Int = 0, bottomEndPercent: Int = 0, bottomStartPercent: Int = 0)

3. RectangleShape:

It renders a plain rectangle. We do not have control over the corner sizes.

@Composable
fun MyUI() {
    Box(
        modifier = Modifier
            .size(size = 100.dp)
            .clip(shape = RectangleShape)
            .background(color = Color.Green)
    ) {
    }
}

Output:

RectangleShape

Note: By default, Box API renders a rectangle. So, in the above code, if you remove the clip() method, you will get the same output.

4. CircleShape:

It creates a circle.

@Composable
fun MyUI() {
    Box(
        modifier = Modifier
            .size(size = 100.dp)
            .clip(shape = CircleShape)
            .background(color = Color.Green)
    ) {
    }
}

Output:

Circle 50 percent

Note: Internally, Jetpack Compose uses RoundedCornerShape(percent = 50) to create CircleShape.

Instead of clip(), we can also use other modifier functions like graphicsLayer, background, and border to render the shapes. Let’s create the above circle with these methods.

Using graphicsLayer:

@Composable
fun MyUI() {
    Box(
        modifier = Modifier
            .size(size = 100.dp)
            .graphicsLayer {
                clip = true // don't forget this
                shape = CircleShape
                // shadowElevation = 20f // you can also set elevation
            }
            .background(color = Color.Green)
    ) {
    }
}

Output:

Circle Shape

Using background:

@Composable
fun MyUI() {
    Box(
        modifier = Modifier
            .size(size = 100.dp)
            .background(color = Color.Green, shape = CircleShape)
    ) {
    }
}

Output:

Circle Shape

Related: How to Create Gradient Backgrounds in Jetpack Compose?

Using border:

@Composable
fun MyUI() {
    Box(
        modifier = Modifier
            .size(size = 100.dp)
            .border(
                width = 4.dp,
                color = Color.Green,
                shape = CircleShape
            )
    ) {
    }
}

Output:

Border Shape Circle

On the android developers site, I found the following custom shape:

Top left corner custom shape

Let’s write the code for it:

@Composable
fun MyUI() {
    Box(
        modifier = Modifier
            .size(size = 100.dp)
            .clip(
                shape = RoundedCornerShape(
                    topStart = 40.dp,
                    topEnd = 0.dp,
                    bottomStart = 0.dp,
                    bottomEnd = 0.dp
                )
            )
            .background(color = Color.Green)
    ) {
    }
}

Output:

Top left corner custom shape

Column with Rounded Corners:

We can create a Column() with rounded corners using the same modifier methods.

@Composable
fun MyUI() {
    Column(
        modifier = Modifier
            .size(120.dp)
            .clip(shape = RoundedCornerShape(size = 32.dp))
            .background(color = Color.Cyan)
    ) {
    }
}

Output:

Column Rounded Corners

Look at these beautiful button styles made with rounded corners.

This is all about shapes in Jetpack Compose. I hope you have learned something new. If you have any doubts, leave a comment below.

Related Articles:

Leave a Comment