blur

Functions summary

Modifier
Modifier.blur(block: BlurScope.() -> Unit)

Draws content with a blur whose radius can vary across the surface.

Cmn
Modifier
Modifier.blur(radius: Dp, edgeTreatment: BlurredEdgeTreatment)

Draws content blurred with the specified radius.

Cmn
Modifier
Modifier.blur(
    radius: BlurRadiusSpec,
    edgeTreatment: BlurredEdgeTreatment,
    alpha: Float
)

Draws content with a blur specified by radius.

Cmn
Modifier
Modifier.blur(
    radiusX: Dp,
    radiusY: Dp,
    edgeTreatment: BlurredEdgeTreatment
)

Draws content blurred with the specified radii.

Cmn

Functions

Modifier.blur

fun Modifier.blur(block: BlurScope.() -> Unit): Modifier

Draws content with a blur whose radius can vary across the surface.

When block assigns BlurScope.radius multiple times, the last assignment wins.

A uniform radius renders on Android 12 (API 31) and above; spatially-varying radii (gradients and custom shaders) require Android 13 (API 33) and above. Below these versions the modifier is ignored.

Usage of this API renders the corresponding composable into a separate graphics layer. Because the blurred content renders a larger area by the blur radius, this layer is explicitly clipped to the content bounds. Introduce additional space around the drawn content by the specified blur radius to remain within the content bounds.

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.blur
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.blur.BlurRadiusSpec
import androidx.compose.ui.unit.dp

Box(
    Modifier.size(200.dp)
        .background(Brush.verticalGradient(listOf(Color.Red, Color.Blue)))
        // Sharp at the top, increasingly blurred toward the bottom.
        .blur(BlurRadiusSpec.verticalGradient(startRadius = 0.dp, endRadius = 24.dp))
)
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.blur
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.blur.BlurRadiusSpec
import androidx.compose.ui.unit.dp

var blurred by remember { mutableStateOf(false) }
val blurRadius by animateDpAsState(if (blurred) 24.dp else 0.dp, label = "blurRadius")
Box(
    Modifier.size(200.dp)
        .background(Brush.verticalGradient(listOf(Color.Red, Color.Blue)))
        // blurRadius is read inside the draw-time block, so the animation invalidates only the
        // draw phase.
        .blur {
            radius = BlurRadiusSpec.verticalGradient(startRadius = 0.dp, endRadius = blurRadius)
        }
        .clickable { blurred = !blurred }
)
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.blur
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.blur.BlurRadiusSpec
import androidx.compose.ui.graphics.blur.BlurStop
import androidx.compose.ui.unit.dp

Box(
    Modifier.size(200.dp)
        .background(Brush.verticalGradient(listOf(Color.Red, Color.Blue)))
        .blur {
            radius =
                BlurRadiusSpec.verticalGradient(
                    listOf(
                        BlurStop(fraction = 0f, radius = 0.dp),
                        BlurStop(fraction = 0.5f, radius = 4.dp),
                        BlurStop(fraction = 1f, radius = 24.dp),
                    )
                )
        }
)
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.blur
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.blur.BlurRadiusSpec
import androidx.compose.ui.unit.DpOffset
import androidx.compose.ui.unit.dp

// Blur direction in degrees, CSS convention: 0° fades toward the top, positive angles turn
// clockwise, so 45° fades toward the top-right.
val angleDegrees = 45f
Box(
    Modifier.size(width = 240.dp, height = 120.dp)
        .background(Brush.verticalGradient(listOf(Color.Red, Color.Blue)))
        .blur {
            val angle = angleDegrees * PI.toFloat() / 180f
            // Unit direction of increasing blur; y is negated because screen y points down.
            val dirX = sin(angle)
            val dirY = -cos(angle)
            // Half-length of the gradient line that exactly spans the layer at this angle:
            // the layer's corners project onto the line at fractions 0 and 1.
            val width = size.width.value
            val height = size.height.value
            val halfLength = (abs(width * dirX) + abs(height * dirY)) / 2f
            val center = DpOffset((width / 2f).dp, (height / 2f).dp)
            val halfLine = DpOffset((dirX * halfLength).dp, (dirY * halfLength).dp)
            radius =
                BlurRadiusSpec.linearGradient(
                    start = center - halfLine,
                    end = center + halfLine,
                    startRadius = 0.dp,
                    endRadius = 16.dp,
                )
        }
)
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.blur
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.blur.BlurRadiusSpec
import androidx.compose.ui.unit.dp

Box(
    Modifier.size(200.dp)
        .background(Brush.verticalGradient(listOf(Color.Red, Color.Blue)))
        // Sharp at the center, blurred toward the edges (center and extent default to the
        // layer).
        .blur { radius = BlurRadiusSpec.radialGradient(startRadius = 0.dp, endRadius = 24.dp) }
)
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.blur
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.blur.BlurRadiusSpec
import androidx.compose.ui.unit.dp

// A RuntimeShader whose alpha channel is a 0..1 blur intensity over the mask's maxRadius.
val radiusShader = remember {
    RuntimeShader(
        """
        uniform float2 size;
        half4 main(float2 coord) {
            // alpha is the blur intensity: 0 at the top (sharp) to 1 at the bottom.
            return half4(0.0, 0.0, 0.0, coord.y / max(size.y, 1.0));
        }
        """
            .trimIndent()
    )
}
// Hoisted so a single configuration is reused; the block re-runs at each resolve with the
// current layer size.
val maskRadius =
    remember(radiusShader) {
        BlurRadiusSpec.shader(maxRadius = 24.dp) { sizePx ->
            radiusShader.setFloatUniform("size", sizePx.width, sizePx.height)
            radiusShader
        }
    }
Box(
    Modifier.size(200.dp)
        .background(Brush.verticalGradient(listOf(Color.Red, Color.Blue)))
        .blur { radius = maskRadius }
)
Parameters
block: BlurScope.() -> Unit

configuration block run against BlurScope

See also
graphicsLayer

Modifier.blur

fun Modifier.blur(
    radius: Dp,
    edgeTreatment: BlurredEdgeTreatment = BlurredEdgeTreatment.Rectangle
): Modifier

Draws content blurred with the specified radius.

Note this effect is only supported on Android 12 and above. Attempts to use this Modifier on older Android versions will be ignored.

Usage of this API renders the corresponding composable into a separate graphics layer. Because the blurred content renders a larger area by the blur radius, this layer is explicitly clipped to the content bounds. Introduce additional space around the drawn content by the specified blur radius to remain within the content bounds.

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.BlurredEdgeTreatment
import androidx.compose.ui.draw.blur
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp

Box(
    Modifier.size(300.dp)
        // Blur content allowing the result to extend beyond the bounds of the original content
        .blur(30.dp, edgeTreatment = BlurredEdgeTreatment.Unbounded)
        .background(Color.Red, CircleShape)
)
import androidx.compose.foundation.Image
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.BlurredEdgeTreatment
import androidx.compose.ui.draw.blur
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp

Image(
    painter = painterResource(R.drawable.circus),
    contentDescription = "sample blurred image",
    // Blur content within the original bounds, clipping the result to a rounded rectangle
    modifier = Modifier.blur(30.dp, BlurredEdgeTreatment(RoundedCornerShape(5.dp))),
)
Parameters
radius: Dp

radius of the blur along both the x and y axis

edgeTreatment: BlurredEdgeTreatment = BlurredEdgeTreatment.Rectangle

strategy used to render pixels outside content bounds

See also
graphicsLayer

Modifier.blur

fun Modifier.blur(
    radius: BlurRadiusSpec,
    edgeTreatment: BlurredEdgeTreatment = BlurredEdgeTreatment.Rectangle,
    alpha: Float = 1.0f
): Modifier

Draws content with a blur specified by radius.

A uniform radius renders on Android 12 (API 31) and above; spatially-varying radii (gradients and custom shaders) require Android 13 (API 33) and above. Below these versions the modifier is ignored.

Usage of this API renders the corresponding composable into a separate graphics layer. Because the blurred content renders a larger area by the blur radius, this layer is explicitly clipped to the content bounds. Introduce additional space around the drawn content by the specified blur radius to remain within content bounds.

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.blur
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.blur.BlurRadiusSpec
import androidx.compose.ui.unit.dp

Box(
    Modifier.size(200.dp)
        .background(Brush.verticalGradient(listOf(Color.Red, Color.Blue)))
        // Sharp at the top, increasingly blurred toward the bottom.
        .blur(BlurRadiusSpec.verticalGradient(startRadius = 0.dp, endRadius = 24.dp))
)
Parameters
radius: BlurRadiusSpec

varying blur radius configuration across the surface

edgeTreatment: BlurredEdgeTreatment = BlurredEdgeTreatment.Rectangle

strategy used to render pixels outside content bounds

alpha: Float = 1.0f

opacity of the blurred content in the 0..1 range

See also
graphicsLayer

Modifier.blur

fun Modifier.blur(
    radiusX: Dp,
    radiusY: Dp,
    edgeTreatment: BlurredEdgeTreatment = BlurredEdgeTreatment.Rectangle
): Modifier

Draws content blurred with the specified radii.

Note this effect is only supported on Android 12 and above. Attempts to use this Modifier on older Android versions will be ignored.

Usage of this API renders the corresponding composable into a separate graphics layer. Because the blurred content renders a larger area by the blur radius, this layer is explicitly clipped to the content bounds. Introduce additional space around the drawn content by the specified blur radius to remain within the content bounds.

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.BlurredEdgeTreatment
import androidx.compose.ui.draw.blur
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp

Box(
    Modifier.size(300.dp)
        // Blur content allowing the result to extend beyond the bounds of the original content
        .blur(30.dp, edgeTreatment = BlurredEdgeTreatment.Unbounded)
        .background(Color.Red, CircleShape)
)
import androidx.compose.foundation.Image
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.BlurredEdgeTreatment
import androidx.compose.ui.draw.blur
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp

Image(
    painter = painterResource(R.drawable.circus),
    contentDescription = "sample blurred image",
    // Blur content within the original bounds, clipping the result to a rounded rectangle
    modifier = Modifier.blur(30.dp, BlurredEdgeTreatment(RoundedCornerShape(5.dp))),
)
Parameters
radiusX: Dp

radius of the blur along the x axis

radiusY: Dp

radius of the blur along the y axis

edgeTreatment: BlurredEdgeTreatment = BlurredEdgeTreatment.Rectangle

strategy used to render pixels outside content bounds

See also
graphicsLayer