How to Create Gradient Backgrounds in Jetpack Compose?

Jetpack Compose Gradient

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

Prerequisites:

First, create an empty Compose project and open the MainActivity file. Create 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.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.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.geometry.Offset
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.dp

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:

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalDensity
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 provides Brush class to create gradient effects. It is a sealed class with the following methods:

  1. horizontalGradient()
  2. verticalGradient()
  3. linearGradient()
  4. radialGradient()
  5. sweepGradient()

Let us look at them one by one.

Horizontal Gradients:

The horizontalGradient() creates a gradient effect from left to right. 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 right of the drawing area.

tileMode – It defines what happens at the edge of the gradient.

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 = 300f,
                    endX = 560f
                )
            )
    ) {
    }
}

Output:

Start and End Positions

If you want set precise positions in dp, 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

We can also add multiple colors.

@Composable
fun MyUI() {
    Box(
        modifier = Modifier
            .size(size = 300.dp)
            .background(
                brush = Brush.horizontalGradient(
                    colors = listOf(
                        Color(0xFFE8A49C),
                        Color(0xFF3C4CAD),
                        Color(0xFF240E8B),
                        Color(0xFFF04393),
                        Color(0xFFF9C449)
                    )
                )
            )
    ) {
    }
}

Output:

Gradient with Multiple Colors

There is also another overload 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 look at them.

Vertical Gradients:

The verticalGradient() creates a gradient effect from top to bottom.

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

Linear Gradients:

The linearGradient() is similar to the above gradients, but we can specify the start and end positions 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:

Let’s create a gradient from the top left corner to the bottom right corner.

@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

Radial Gradients:

The radialGradient() creates a gradient effect that starts from the middle and spreads outwards.

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

Sweep Gradients:

sweepGradient() 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.

This is all about creating gradient backgrounds in Jetpack Compose. I hope you have learned something new. If you have any doubts, comment below.

Related Articles:


References:

Leave a Comment