
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:

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:

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:

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:

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:

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:

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:

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:

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