How to Create Gradient Backgrounds in Jetpack Compose?

Jetpack Compose Gradient

In this article, we will learn how to create gradient backgrounds in Jetpack Compose using the built-in Brush API.

Prerequisites:

Jetpack Compose provides Brush class to create gradient effects. It is a sealed class. It has the following methods:

  • horizontalGradient()
  • verticalGradient()
  • linearGradient()
  • radialGradient()
  • sweepGradient()

Let us look at them one by one.

horizontalGradient:

It creates a horizontal gradient. The colors are evenly distributed.

@Stable
fun horizontalGradient(
    colors: List<Color>,
    startX: Float = 0.0f,
    endX: Float = Float.POSITIVE_INFINITY,
    tileMode: TileMode = TileMode.Clamp
): Brush

It takes multiple parameters:

colors – List of colors. You should specify at least two.

startX – Starting x position of the gradient. Its default value is 0 which means left of the drawing area.

endX – Ending x position of the gradient. Its default value is Float.POSITIVE_INFINITY which indicates the left of the drawing area.

tileMode – It defines what happens at the edge of the gradient (see the docs).

Here is a simple example:

@Composable
fun MyUI() {

    Box(
        modifier = Modifier
            .size(size = 300.dp)
            .background(
                brush = Brush.horizontalGradient(
                    colors = listOf(
                        Color.Cyan,
                        Color.Magenta
                    )
                )
            )
    ) {
    }
}

Output:

Horizontal Gradient Example

Let’s change the starting and ending positions:

@Composable
fun MyUI() {

    Box(
        modifier = Modifier
            .size(size = 300.dp)
            .background(
                brush = Brush.horizontalGradient(
                    colors = listOf(
                        Color.Cyan,
                        Color.Magenta
                    ),
                    startX = 200f,
                    endX = 400f
                )
            )
    ) {
    }
}

Output:

Start and End Positions

If you want set precise positions in dp, we should convert dp to pixels.

@Composable
fun MyUI() {

    val pxStart = with(LocalDensity.current) { 100.dp.toPx() }
    val pxEnd = with(LocalDensity.current) { 250.dp.toPx() }

    Box(
        modifier = Modifier
            .size(size = 300.dp)
            .background(
                brush = Brush.horizontalGradient(
                    colors = listOf(
                        Color.Cyan,
                        Color.Magenta
                    ),
                    startX = pxStart,
                    endX = pxEnd
                )
            )
    ) {
    }
}

Output:

Dp to Px

There is also another definition of the horizontalGradient() which accepts color stops:

@Stable
fun horizontalGradient(
    vararg colorStops: Pair<Float, Color>,
    startX: Float = 0.0f,
    endX: Float = Float.POSITIVE_INFINITY,
    tileMode: TileMode = TileMode.Clamp
): Brush

Example:

@Composable
fun MyUI() {

    Box(
        modifier = Modifier
            .size(size = 300.dp)
            .background(
                brush = Brush.horizontalGradient(
                    0.0f to Color.Yellow,
                    0.5f to Color.Cyan,
                    1.0f to Color.Magenta,
                    startX = 0f,
                    endX = Float.POSITIVE_INFINITY
                )
            )
    ) {
    }
}

Output:

Color Stops Gradient

The offset values represent the width of the box in terms of percentage.

0.0f represents 0% (left end of the box)
0.5f represents 50% (center of the box)
1.0f represents 100% (right end of the box)

From 0% to 50%, it creates a gradient with Yellow and Cyan. From 50% to 100%, it creates a gradient with Cyan and Magenta.

The remaining gradient functions are similar to the horizontalGradient. Let’s see look at them.

verticalGradient:

It creates a vertical gradient.

with colors:

fun verticalGradient(
    colors: List<Color>,
    startY: Float = 0.0f,
    endY: Float = Float.POSITIVE_INFINITY,
    tileMode: TileMode = TileMode.Clamp
): Brush

with color stops:

fun verticalGradient(
    vararg colorStops: Pair<Float, Color>,
    startY: Float = 0.0f,
    endY: Float = Float.POSITIVE_INFINITY,
    tileMode: TileMode = TileMode.Clamp
): Brush

Example:

@Composable
fun MyUI() {

    Box(
        modifier = Modifier
            .size(size = 300.dp)
            .background(
                brush = Brush.verticalGradient(
                  colors = listOf(Color.Green, Color.Yellow)
                )
            )
    ) {
    }
}

Output:

Vertical

linearGradient:

It creates a linear gradient. We can provide start and end coordinates using the Offset function.

witch colors:

fun linearGradient(
    colors: List<Color>,
    start: Offset = Offset.Zero,
    end: Offset = Offset.Infinite,
    tileMode: TileMode = TileMode.Clamp
): Brush

with color stops:

fun linearGradient(
    vararg colorStops: Pair<Float, Color>,
    start: Offset = Offset.Zero,
    end: Offset = Offset.Infinite,
    tileMode: TileMode = TileMode.Clamp
): Brush

Example:

@Composable
fun MyUI() {

    // convert the box size to pixels
    val boxSize = with(LocalDensity.current) { 300.dp.toPx() }

    Box(
        modifier = Modifier
            .size(size = 300.dp)
            .background(
                brush = Brush.linearGradient(
                    colors = listOf(Color.Green, Color.Yellow),
                    start = Offset(0f, 0f), // top left corner
                    end = Offset(boxSize, boxSize) // bottom right corner
                )
            )
    ) {
    }
}

Output:

Linear Gradient

radialGradient:

It creates a radial gradient.

with colors:

fun radialGradient(
    colors: List<Color>,
    center: Offset = Offset.Unspecified,
    radius: Float = Float.POSITIVE_INFINITY,
    tileMode: TileMode = TileMode.Clamp
): Brush

with color stops:

fun radialGradient(
    vararg colorStops: Pair<Float, Color>,
    center: Offset = Offset.Unspecified,
    radius: Float = Float.POSITIVE_INFINITY,
    tileMode: TileMode = TileMode.Clamp
): Brush

Example:

@Composable
fun MyUI() {

    // convert the box size to pixels
    val boxSize = with(LocalDensity.current) { 300.dp.toPx() }

    Box(
        modifier = Modifier
            .size(size = 300.dp)
            .background(
                brush = Brush.radialGradient(
                    colors = listOf(Color.Green, Color.Yellow),
                    center = Offset(x = boxSize / 2, y = boxSize / 2) // center
                )
            )
    ) {
    }
}

Output:

radial

sweepGradient:

It creates a sweep gradient. It is similar to the conic gradient function in CSS. The sweep starts relative to 3 o’clock and ends at the same starting position.

with colors:

fun sweepGradient(colors: List<Color>, center: Offset = Offset.Unspecified): Brush

with color stops:

fun sweepGradient(
    vararg colorStops: Pair<Float, Color>,
    center: Offset = Offset.Unspecified
): Brush

Example:

@Composable
fun MyUI() {

    // convert the box size to pixels
    val boxSize = with(LocalDensity.current) { 300.dp.toPx() }

    Box(
        modifier = Modifier
            .size(size = 300.dp)
            .background(
                brush = Brush.sweepGradient(
                    colors = listOf(Color.Green, Color.Yellow),
                    center = Offset(x = boxSize / 2, y = boxSize / 2) // center
                )
            )
    ) {
    }
}

Output:

Sweep Gradient

Look at these beautiful loading dialog and button styles designed using these gradient functions.

Leave a Comment