Desfoque no Compose

Os efeitos de desfoque suavizam os detalhes visuais, criam profundidade de campo fotográfica e chamam a atenção para os elementos da interface em primeiro plano. No Jetpack Compose, use Modifier.blur para desfocar o conteúdo desenhado em um elemento combinável, incluindo imagens, formas, texto e contêineres de layout. A aplicação de Modifier.blur renderiza o elemento combinável em uma camada de gráficos separada.

À esquerda: a imagem original. Centro: a imagem com um desfoque uniforme aplicado em toda a superfície. À direita: a imagem com um desfoque progressivo que é nítido na parte de cima e aumenta em direção à parte de baixo.
Figura 1. À esquerda: a imagem original. Centro: a imagem com um desfoque uniforme aplicado em toda a superfície. À direita: a imagem com um desfoque progressivo que é nítido na parte de cima e aumenta em direção à parte de baixo.

Dependendo das suas metas de design, é possível variar o desfoque de duas maneiras:

  • Desfoque uniforme: aplica um raio de desfoque constante em todo o elemento combinável, de forma igual em ambos os eixos ou com raios horizontais e verticais independentes (radiusX, radiusY).
  • Desfoque progressivo: varia o raio de desfoque espacialmente no elemento que pode ser composto usando gradientes BlurRadiusSpec ou um Shader personalizado.

Aplicar um desfoque uniforme

Para aplicar um desfoque constante em todo um elemento combinável, transmita um raio Dp para Modifier.blur. Transmita um único valor radius para desfocar o conteúdo igualmente nos eixos horizontal (X) e vertical (Y):

@Composable
fun UniformBlurExample() {
    Image(
        painter = painterResource(id = R.drawable.dog),
        contentDescription = stringResource(id = R.string.dog_content_description),
        contentScale = ContentScale.Crop,
        modifier = Modifier
            .size(150.dp)
            .blur(
                radius = 8.dp,
                edgeTreatment = BlurredEdgeTreatment(RoundedCornerShape(8.dp)),
            ),
    )
}

Um cachorro desfocado de maneira uniforme nos eixos horizontal e vertical.
Figura 2. Um cachorro desfocado de maneira uniforme nos eixos horizontal e vertical.

Para criar um efeito de desfoque de movimento direcional, transmita valores separados de radiusX e radiusY para Modifier.blur. Tanto radiusX quanto radiusY precisam ser maiores que 0.dp para que o efeito de desfoque seja aplicado, conforme mostrado no exemplo a seguir:

@Composable
fun DirectionalBlurExample() {
    Image(
        painter = painterResource(id = R.drawable.dog),
        contentDescription = stringResource(id = R.string.dog_content_description),
        contentScale = ContentScale.Crop,
        modifier = Modifier
            .size(150.dp)
            .blur(
                radiusX = 10.dp,
                radiusY = 2.dp,
                edgeTreatment = BlurredEdgeTreatment(RoundedCornerShape(8.dp)),
            ),
    )
}

Um cachorro com um forte efeito de desfoque de movimento horizontal.
Figura 3. Imagem quadrada de um cachorro com um forte efeito de desfoque de movimento horizontal.

Aplicar um desfoque progressivo

O desfoque progressivo varia o raio de desfoque em um elemento combinável, criando uma transição suave entre regiões nítidas e desfocadas.

Transmita um BlurRadiusSpec para Modifier.blur. Por exemplo, use BlurRadiusSpec.verticalGradient com startRadius = 0.dp e endRadius = 6.dp para manter a parte de cima de uma imagem nítida enquanto desfoca progressivamente em direção à parte de baixo, como mostrado no exemplo a seguir:

@Composable
fun ProgressiveBlurExample() {
    Image(
        painter = painterResource(id = R.drawable.dog),
        contentDescription = stringResource(id = R.string.dog_content_description),
        contentScale = ContentScale.Crop,
        modifier = Modifier
            .size(150.dp)
            .blur(
                // Sharp at the top (0.dp), progressively blurred toward the bottom (6.dp)
                blurRadiusSpec = BlurRadiusSpec.verticalGradient(
                    startRadius = 0.dp,
                    endRadius = 6.dp,
                ),
                edgeTreatment = BlurredEdgeTreatment(RoundedCornerShape(8.dp)),
            ),
    )
}

Um cachorro que está nítido na parte de cima e fica gradualmente desfocado na parte de baixo.
Figura 4. Imagem de um cachorro que é nítida na parte de cima e fica gradualmente desfocada na parte de baixo.

Especificar gradientes de desfoque com BlurRadiusSpec

No BlurRadiusSpec, as medidas são definidas em Dp e se ajustam automaticamente ao tamanho e à densidade de exibição da camada quando desenhadas. Os desfoques espacialmente variáveis têm um limite de 150 pixels após a conversão, enquanto o BlurRadiusSpec.uniform não tem limite.

A tabela a seguir lista as funções de fábrica disponíveis em BlurRadiusSpec:

Fábrica de BlurRadiusSpec Descrição
BlurRadiusSpec.verticalGradient Muda suavemente o raio de desfoque na vertical, de cima (0f) para baixo (1f), em toda a camada.
BlurRadiusSpec.horizontalGradient Muda suavemente o raio de desfoque na horizontal, da borda esquerda (0f) para a direita (1f).
BlurRadiusSpec.linearGradient Aplica uma transição de desfoque direcional ao longo de uma linha reta que conecta coordenadas DpOffset específicas.
BlurRadiusSpec.radialGradient Espalha o desfoque para fora de um ponto focal em direção ao limite de fallOffRadius.
BlurRadiusSpec.uniform Aplica um raio de desfoque uniforme em toda a camada.
BlurRadiusSpec.shader Usa o canal Alfa de um Shader personalizado para controlar e dimensionar o maxRadius em cada pixel.

Personalizar a distribuição de desfoque com BlurStop

Os desfoques de gradiente padrão interpolam linearmente entre 0f e 1f. Para personalizar a distribuição do desfoque em uma superfície, como desfocar várias bordas ou manter uma seção central completamente nítida, transmita um List<BlurStop> contendo de 2 a 16 entradas BlurStop para verticalGradient, horizontalGradient, linearGradient ou radialGradient. Defina o seguinte para cada entrada BlurStop:

  • fraction: a posição relativa ao longo do gradiente de 0.0f a 1.0f. As paradas são classificadas automaticamente por fração.
  • radius: o raio de desfoque em Dp aplicado nessa posição de fração.

Por exemplo, quatro paradas desfocam as bordas de cima e de baixo de uma imagem, mantendo o meio completamente nítido, como mostrado no exemplo a seguir:

@Composable
fun MultiStopBlurExample() {
    Image(
        painter = painterResource(id = R.drawable.dog),
        contentDescription = stringResource(id = R.string.dog_content_description),
        contentScale = ContentScale.Crop,
        modifier = Modifier
            .size(150.dp)
            .blur(
                // Blurred at the top and bottom edges, sharp in the middle (0.3f..0.7f)
                blurRadiusSpec = BlurRadiusSpec.verticalGradient(
                    stops = listOf(
                        BlurStop(fraction = 0.0f, radius = 20.dp),
                        BlurStop(fraction = 0.3f, radius = 0.dp),
                        BlurStop(fraction = 0.7f, radius = 0.dp),
                        BlurStop(fraction = 1.0f, radius = 20.dp),
                    ),
                ),
                edgeTreatment = BlurredEdgeTreatment.Unbounded,
            ),
    )
}

Um cachorro com as bordas superior e inferior desfocadas, mantendo a faixa horizontal do meio em foco nítido.
Figura 5. Imagem de um cachorro com as bordas de cima e de baixo desfocadas, mantendo a faixa horizontal do meio em foco nítido.

Configurar propriedades de camada com BlurScope

Em vez de transmitir blurRadiusSpec diretamente, é possível transmitir um bloco de configuração para Modifier.blur { ... }. Esse bloco é executado dentro de BlurScope, que dá acesso direto à densidade do layout e às seguintes propriedades:

  • size: DpSize: a largura e a altura medidas da camada desfocada em Dp, que define o espaço de coordenadas para a geometria do gradiente.
  • blurRadiusSpec: BlurRadiusSpec: a configuração do raio de desfoque na superfície. O padrão é BlurRadiusSpec.uniform(0.dp) (sem desfoque).
  • edgeTreatment: BlurredEdgeTreatment: estratégia usada para amostrar e recortar pixels fora dos limites do conteúdo. O padrão é BlurredEdgeTreatment.Rectangle.
  • alpha: Float: opacidade da camada desfocada no intervalo 0f..1f. O padrão é 1f.

Como o bloco BlurScope é executado durante a fase da camada de gráficos, após a medição e o layout, é possível calcular a geometria do gradiente de size sem acionar a recomposição.

Controlar o corte de bordas com BlurredEdgeTreatment

Como o desfoque usa pixels vizinhos dentro do raio de desfoque, a saída desfocada se estende além dos limites do conteúdo original pelo raio de desfoque. BlurredEdgeTreatment determina como os pixels fora dos limites originais são amostrados e se o resultado é cortado em uma forma.

O BlurredEdgeTreatment funciona com desfoques uniformes e progressivos:

BlurredEdgeTreatment Comportamento Saída
BlurredEdgeTreatment.Rectangle (padrão) Corta o resultado do desfoque para os limites retangulares do conteúdo original e usa os pixels de borda mais próximos (TileMode.Clamp). Uma imagem desfocada de um cachorro cortada em um limite retangular nítido.
BlurredEdgeTreatment(shape) Recorta o resultado do desfoque para o Shape especificado (como RoundedCornerShape(8.dp)) e faz uma amostragem dos pixels de borda mais próximos (TileMode.Clamp). Mantém o resultado desfocado nítido no limite da forma sem ultrapassar os limites originais. Uma imagem desfocada de um cachorro recortada em uma forma de canto arredondado com bordas nítidas.
BlurredEdgeTreatment.Unbounded Não corta o resultado do desfoque (TileMode.Decal). Os pixels fora dos limites do conteúdo usam a cor preta transparente, fazendo com que as bordas externas da imagem pareçam difusas e desfocadas além dos limites originais. Uma imagem desfocada de um cachorro com bordas que se dissolvem suavemente além dos limites originais.

Para ver como essas APIs se combinam em padrões de interface completos, como esmaecer as bordas do conteúdo de rolagem, destacar um ponto focal ou mascarar um desfoque com um sombreador personalizado, consulte Casos de uso comuns de desfoque.