Sfocatura in Compose

Gli effetti di sfocatura ammorbidiscono i dettagli visivi, creano una profondità di campo fotografica e attirano l'attenzione sugli elementi UI in primo piano. In Jetpack Compose, utilizza Modifier.blur per sfocare i contenuti disegnati all'interno di un composable, tra cui immagini, forme, testo e contenitori di layout. L'applicazione di Modifier.blur esegue il rendering del composable in un livello grafico separato.

A sinistra: l'immagine originale. Al centro: l'immagine con una sfocatura uniforme applicata su tutta la superficie. A destra: l'immagine con una sfocatura progressiva che è nitida in alto e aumenta verso il basso.
Figura 1. A sinistra: l'immagine originale. Al centro: l'immagine con una sfocatura uniforme applicata su tutta la superficie. A destra: l'immagine con una sfocatura progressiva che è nitida in alto e aumenta verso il basso.

A seconda dei tuoi obiettivi di progettazione, puoi variare la sfocatura in due modi:

  • Sfocatura uniforme: applica un raggio di sfocatura costante all'intero composable, in modo uniforme su entrambi gli assi o con raggi orizzontali e verticali indipendenti (radiusX, radiusY).
  • Sfocatura progressiva: varia il raggio di sfocatura nello spazio all'interno del composable utilizzando gradienti BlurRadiusSpec o un Shader personalizzato.

Applica una sfocatura uniforme

Per applicare una sfocatura costante a un intero composable, passa un raggio Dp a Modifier.blur. Passa un singolo valore radius per sfocare i contenuti in modo uniforme lungo gli assi orizzontale (X) e verticale (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)),
            ),
    )
}

Un cane sfocato in modo uniforme sia sull'asse orizzontale che su quello verticale.
Figura 2. Un cane sfocato in modo uniforme sia sull'asse orizzontale che su quello verticale.

Per creare un effetto di sfocatura da movimento direzionale, passa valori radiusX e radiusY separati a Modifier.blur. Sia radiusX che radiusY devono essere maggiori di 0.dp per applicare l'effetto di sfocatura, come mostrato nell'esempio seguente:

@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)),
            ),
    )
}

Un cane con un forte effetto di sfocatura di movimento orizzontale.
Figura 3. Un'immagine quadrata di un cane con un forte effetto di sfocatura di movimento orizzontale.

Applica una sfocatura progressiva

Una sfocatura progressiva varia il raggio di sfocatura in un composable, creando una transizione fluida tra le regioni nitide e quelle sfocate.

Passa un BlurRadiusSpec a Modifier.blur. Ad esempio, utilizza BlurRadiusSpec.verticalGradient con startRadius = 0.dp e endRadius = 6.dp per mantenere nitida la parte superiore di un'immagine sfocandola progressivamente verso il basso, come mostrato nell'esempio seguente:

@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)),
            ),
    )
}

Un cane nitido in alto e gradualmente sfocato verso il basso.
Figura 4. Un'immagine di un cane che è nitida in alto e diventa gradualmente sfocata verso il basso.

Specifica i gradienti di sfocatura con BlurRadiusSpec

In BlurRadiusSpec, le misurazioni sono impostate in Dp e si adattano automaticamente alle dimensioni e alla densità di visualizzazione del livello quando vengono disegnate. Le sfocature con variazione spaziale hanno un limite di 150 pixel una volta convertite, mentre BlurRadiusSpec.uniform non ha limiti.

La tabella seguente elenca le funzioni di fabbrica disponibili su BlurRadiusSpec:

Fabbrica di BlurRadiusSpec Descrizione
BlurRadiusSpec.verticalGradient Modifica in modo uniforme il raggio di sfocatura verticalmente dall'alto (0f) al basso (1f) nel livello.
BlurRadiusSpec.horizontalGradient Modifica gradualmente il raggio di sfocatura in orizzontale dal bordo sinistro (0f) al bordo destro (1f).
BlurRadiusSpec.linearGradient Applica una transizione di sfocatura direzionale lungo una linea retta che collega coordinate DpOffset specifiche.
BlurRadiusSpec.radialGradient Estende la sfocatura verso l'esterno da un punto focale verso il bordo fallOffRadius.
BlurRadiusSpec.uniform Applica un raggio di sfocatura uniforme all'intero livello.
BlurRadiusSpec.shader Utilizza il canale alfa di un Shader personalizzato per controllare e scalare il maxRadius in ogni pixel.

Personalizza la distribuzione della sfocatura con BlurStop

Le sfocature con gradiente standard interpolano linearmente tra 0f e 1f. Per personalizzare la distribuzione della sfocatura su una superficie, ad esempio sfocando più bordi o mantenendo una sezione centrale completamente nitida, passa un List<BlurStop> contenente da 2 a 16 voci BlurStop a verticalGradient, horizontalGradient, linearGradient o radialGradient. Definisci quanto segue per ogni voce BlurStop:

  • fraction: la posizione relativa lungo il gradiente da 0.0f a 1.0f. Le fermate vengono ordinate automaticamente per frazione.
  • radius: il raggio di sfocatura in Dp applicato in quella posizione della frazione.

Ad esempio, quattro stop sfocano i bordi superiore e inferiore di un'immagine, mantenendo la parte centrale completamente nitida, come mostrato nell'esempio seguente:

@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,
            ),
    )
}

Un cane con i bordi superiore e inferiore sfocati, mentre la striscia orizzontale centrale è perfettamente a fuoco.
Figura 5. Un'immagine di un cane con i bordi superiore e inferiore sfocati, mentre la striscia orizzontale centrale è perfettamente a fuoco.

Configura le proprietà dei livelli con BlurScope

Anziché passare direttamente blurRadiusSpec, puoi passare un blocco di configurazione a Modifier.blur { ... }. Questo blocco viene eseguito all'interno di BlurScope, che ti consente di accedere direttamente alla densità del layout e alle seguenti proprietà:

  • size: DpSize: la larghezza e l'altezza misurate del livello sfocato in Dp, che definisce lo spazio delle coordinate per la geometria del gradiente.
  • blurRadiusSpec: BlurRadiusSpec: la configurazione del raggio di sfocatura sulla superficie. Il valore predefinito è BlurRadiusSpec.uniform(0.dp) (nessuna sfocatura).
  • edgeTreatment: BlurredEdgeTreatment: strategia utilizzata per campionare e ritagliare i pixel al di fuori dei limiti dei contenuti. Il valore predefinito è BlurredEdgeTreatment.Rectangle.
  • alpha: Float: opacità del livello sfocato nell'intervallo 0f..1f. Il valore predefinito è 1f.

Poiché il blocco BlurScope viene eseguito durante la fase del livello grafico, dopo la misurazione e il layout, puoi calcolare la geometria del gradiente da size senza attivare la ricomposizione.

Controlla il ritaglio dei bordi con BlurredEdgeTreatment

Poiché la sfocatura campiona i pixel adiacenti all'interno del raggio di sfocatura, l'output sfocato si estende oltre i limiti dei contenuti originali in base al raggio di sfocatura. BlurredEdgeTreatment determina il modo in cui i pixel al di fuori dei limiti originali vengono campionati e se il risultato viene ritagliato in una forma.

BlurredEdgeTreatment funziona sia con le sfocature uniformi che con quelle progressive:

BlurredEdgeTreatment Comportamento Output
BlurredEdgeTreatment.Rectangle (valore predefinito) Ritaglia il risultato della sfocatura in base ai limiti rettangolari dei contenuti originali e campiona i pixel dei bordi più vicini (TileMode.Clamp). Un'immagine sfocata di un cane ritagliata in un bordo rettangolare nitido.
BlurredEdgeTreatment(shape) Ritaglia il risultato della sfocatura in base alla forma Shape specificata (ad esempio RoundedCornerShape(8.dp)) e campiona i pixel dei bordi più vicini (TileMode.Clamp). Mantiene nitido il risultato della sfocatura sul bordo della forma senza sbavature al di fuori dei limiti originali. Un'immagine sfocata di un cane ritagliata in una forma con angoli arrotondati e bordi netti.
BlurredEdgeTreatment.Unbounded Non ritaglia il risultato della sfocatura (TileMode.Decal). I pixel al di fuori dei limiti dei contenuti campionano il nero trasparente, facendo apparire i bordi esterni dell'immagine sfocati e confusi oltre i limiti originali. Un'immagine sfocata di un cane i cui bordi sfumano delicatamente oltre i limiti originali.

Per scoprire come queste API si combinano in pattern di UI completi, ad esempio per sfumare i bordi dei contenuti a scorrimento, mettere in evidenza un punto focale o mascherare una sfocatura con uno shader personalizzato, consulta Casi d'uso comuni della sfocatura.