Personalizzare un'immagine

Puoi personalizzare le immagini utilizzando le proprietà di un Image componibile (contentScale, colorFilter). Puoi anche applicare modificatori esistenti per applicare effetti diversi al tuo Image. I modificatori possono essere utilizzati su qualsiasi componibile, non solo sul componibile Image, mentre contentScale e colorFilter sono parametri espliciti del componibile Image.

Scala dei contenuti

Specifica un'opzione contentScale per ritagliare o modificare il modo in cui un'immagine viene ridimensionata all'interno dei suoi limiti. Per impostazione predefinita, se non specifichi un'opzione contentScale, viene utilizzato ContentScale.Fit.

Nell'esempio seguente, il composable Image è limitato a una dimensione di 150 dp con un bordo e lo sfondo è impostato su giallo nel composable Image per mostrare le diverse opzioni ContentScale nella tabella seguente.

val imageModifier = Modifier
    .size(150.dp)
    .border(BorderStroke(1.dp, Color.Black))
    .background(Color.Yellow)
Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_description),
    contentScale = ContentScale.Fit,
    modifier = imageModifier
)

L'impostazione di diverse opzioni di ContentScale genera output diversi. La tabella seguente ti aiuta a scegliere la modalità ContentScale corretta:

Immagine di origine L'origine del ritratto, che mostra un cane. La fonte del paesaggio, che mostra un cane diverso.
ContentScale Risultato - Immagine verticale: Risultato - Immagine orizzontale:
ContentScale.Fit: ridimensiona l'immagine in modo uniforme, mantenendo le proporzioni (impostazione predefinita). Se i contenuti sono più piccoli delle dimensioni, l'immagine viene scalata per adattarsi ai limiti. Il ritratto di un cane scalato in modo uniforme. Un paesaggio con un cane scalato in modo uniforme.
ContentScale.Crop: ritaglia l'immagine al centro nello spazio disponibile. Un'immagine verticale ritagliata per riempire un fotogramma quadrato, che mostra solo la parte centrale dell'immagine. Un'immagine orizzontale ritagliata per riempire un fotogramma quadrato, che mostra solo la parte centrale dell'immagine.
ContentScale.FillHeight: ridimensiona l'origine mantenendo le proporzioni in modo che i limiti corrispondano all'altezza della destinazione. Un'immagine verticale ridimensionata per riempire l'altezza di un riquadro quadrato, che mostra l'immagine completa con lo sfondo giallo visibile a sinistra e a destra. Un'immagine orizzontale scalata per riempire l'altezza di un fotogramma quadrato, con i lati ritagliati.
ContentScale.FillWidth: ridimensiona l'origine mantenendo le proporzioni in modo che i limiti corrispondano alla larghezza della destinazione. Un'immagine verticale scalata per riempire la larghezza di un fotogramma quadrato, con la parte superiore e inferiore ritagliate. Un'immagine orizzontale ridimensionata per riempire la larghezza di un frame quadrato, che mostra l'immagine completa con lo sfondo giallo visibile nella parte superiore e inferiore.
ContentScale.FillBounds: ridimensiona i contenuti verticalmente e orizzontalmente in modo non uniforme per riempire i limiti della destinazione. Nota: questo distorce le immagini se le inserisci in contenitori che non corrispondono alle proporzioni esatte dell'immagine. Un'immagine verticale distorta per riempire completamente un frame quadrato, allungando l'immagine. Un'immagine orizzontale distorta per riempire completamente un fotogramma quadrato, allungando l'immagine.
ContentScale.Inside: ridimensiona l'origine per mantenere le proporzioni all'interno dei limiti della destinazione. Se l'origine è minore o uguale alla destinazione in entrambe le dimensioni, si comporta in modo simile a None. I contenuti saranno sempre contenuti all'interno dei limiti. Se i contenuti sono più piccoli dei limiti, non verrà applicata alcuna scalabilità. Immagine di origine più grande dei limiti: Un'immagine verticale, originariamente più grande dei suoi limiti quadrati, ridimensionata per adattarsi mantenendo le proporzioni, che mostra uno sfondo giallo sui lati. Immagine di origine più piccola dei limiti: Un'immagine verticale, originariamente più piccola dei suoi limiti quadrati, visualizzata nelle sue dimensioni originali all'interno del frame, che mostra uno sfondo giallo intorno. Immagine di origine più grande dei limiti: Un'immagine orizzontale, originariamente più grande dei suoi limiti quadrati, ridimensionata per adattarsi mantenendo le proporzioni, che mostra uno sfondo giallo nella parte superiore e inferiore. Immagine di origine più piccola dei limiti: Un'immagine orizzontale, originariamente più piccola dei suoi limiti quadrati, visualizzata nelle sue dimensioni originali all'interno del frame, con uno sfondo giallo intorno.
ContentScale.None: non applicare alcuna scalabilità all'origine. Se i contenuti sono più piccoli dei limiti della destinazione, non verranno scalati per adattarsi all'area. Immagine di origine più grande dei limiti: Un'immagine verticale, originariamente più grande dei suoi limiti quadrati, visualizzata nelle sue dimensioni originali, con parti che si estendono oltre la parte superiore e inferiore del frame. Immagine di origine più piccola dei limiti: Un'immagine verticale, originariamente più piccola dei suoi limiti quadrati, visualizzata nelle sue dimensioni originali all'interno del frame, che mostra uno sfondo giallo intorno. Immagine di origine più grande dei limiti: Un'immagine orizzontale, originariamente più grande dei suoi limiti quadrati, visualizzata nelle sue dimensioni originali, con parti che si estendono oltre i lati sinistro e destro del frame. Immagine di origine più piccola dei limiti: Un'immagine orizzontale, originariamente più piccola dei suoi limiti quadrati, visualizzata nelle sue dimensioni originali all'interno del frame, con uno sfondo giallo intorno.

Ritagliare un elemento componibile Image in una forma

Per adattare un'immagine a una forma, utilizza il modificatore clip integrato. Per ritagliare un'immagine in una forma circolare, utilizza Modifier.clip(CircleShape):

Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_description),
    contentScale = ContentScale.Crop,
    modifier = Modifier
        .size(200.dp)
        .clip(CircleShape)
)

L'immagine di un cane ritagliata in un cerchio perfetto.
Figura 1. Ritagliare un'immagine con CircleShape.

Per una forma con angoli arrotondati, utilizza Modifier.clip(RoundedCornerShape(16.dp)), con le dimensioni degli angoli che vuoi arrotondare:

Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_description),
    contentScale = ContentScale.Crop,
    modifier = Modifier
        .size(200.dp)
        .clip(RoundedCornerShape(16.dp))
)

Un'immagine quadrata di un cane ritagliata con angoli arrotondati.
Figura 2. Ritagliare un'immagine con RoundedCornerShape.

Puoi anche creare una forma di ritaglio personalizzata estendendo Shape e fornendo un Path per la forma da ritagliare:

class SquashedOval : Shape {
    override fun createOutline(
        size: Size,
        layoutDirection: LayoutDirection,
        density: Density
    ): Outline {
        val path = Path().apply {
            // We create an Oval that starts at ¼ of the width, and ends at ¾ of the width of the container.
            addOval(
                Rect(
                    left = size.width / 4f,
                    top = 0f,
                    right = size.width * 3 / 4f,
                    bottom = size.height
                )
            )
        }
        return Outline.Generic(path = path)
    }
}

Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_description),
    contentScale = ContentScale.Crop,
    modifier = Modifier
        .size(200.dp)
        .clip(SquashedOval())
)

Un'immagine quadrata di un cane ritagliata in una forma ovale personalizzata.
Figura 3. Ritagliare un'immagine con una forma di tracciato personalizzata.

Aggiungere un bordo a un composable Image

Un'operazione comune consiste nel combinare Modifier.border() con Modifier.clip() per creare un bordo intorno a un'immagine:

val borderWidth = 4.dp
Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_description),
    contentScale = ContentScale.Crop,
    modifier = Modifier
        .size(150.dp)
        .border(
            BorderStroke(borderWidth, Color.Yellow),
            CircleShape
        )
        .padding(borderWidth)
        .clip(CircleShape)
)

Un'immagine quadrata di un cane, ritagliata in un cerchio, con un bordo giallo intorno alla forma circolare.
Figura 4. Un'immagine ritagliata con un bordo intorno.

Per creare un bordo sfumato, puoi utilizzare l'API Brush per disegnare un bordo sfumato arcobaleno intorno all'immagine:

val rainbowColorsBrush = remember {
    Brush.sweepGradient(
        listOf(
            Color(0xFF9575CD),
            Color(0xFFBA68C8),
            Color(0xFFE57373),
            Color(0xFFFFB74D),
            Color(0xFFFFF176),
            Color(0xFFAED581),
            Color(0xFF4DD0E1),
            Color(0xFF9575CD)
        )
    )
}
val borderWidth = 4.dp
Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_description),
    contentScale = ContentScale.Crop,
    modifier = Modifier
        .size(150.dp)
        .border(
            BorderStroke(borderWidth, rainbowColorsBrush),
            CircleShape
        )
        .padding(borderWidth)
        .clip(CircleShape)
)

Un'immagine circolare di un cane con un bordo sfumato arcobaleno intorno alla forma circolare.
Figura 5. Bordo circolare con sfumatura arcobaleno.

Impostare un formato personalizzato

Per trasformare un'immagine in un formato personalizzato, utilizza Modifier.aspectRatio(16f/9f) per fornire un formato personalizzato per un'immagine (o qualsiasi componente).

Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_description),
    modifier = Modifier.aspectRatio(16f / 9f)
)

Un'immagine quadrata di un cane, trasformata in proporzioni 16:9, che la rendono più larga e più corta.
Figura 6. Utilizzo di Modifier.aspectRatio(16f/9f) su un Image.

Filtro colore: trasforma i colori dei pixel dell'immagine

Il composable Image ha un parametro colorFilter che può modificare l'output dei singoli pixel dell'immagine.

Immagini con tinta

L'utilizzo di ColorFilter.tint(color, blendMode) applica una modalità di fusione con il colore specificato al composable Image. ColorFilter.tint(color, blendMode) utilizza BlendMode.SrcIn per colorare i contenuti, il che significa che il colore fornito viene mostrato dove l'immagine viene visualizzata sullo schermo. Ciò è utile per icone e vettori che devono avere temi diversi.

Image(
    painter = painterResource(id = R.drawable.baseline_directions_bus_24),
    contentDescription = stringResource(id = R.string.bus_content_description),
    colorFilter = ColorFilter.tint(Color.Yellow)
)

Un'immagine di un autobus con una tonalità gialla applicata.
Figura 7. ColorFilter.tint applicato con BlendMode.SrcIn.

Altri BlendMode producono effetti diversi. Ad esempio, l'impostazione BlendMode.Darken con un Color.Green su un'immagine produce il seguente risultato:

Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_description),
    colorFilter = ColorFilter.tint(Color.Green, blendMode = BlendMode.Darken)
)

Un cane con una tonalità verde applicata utilizzando BlendMode.Darken, che produce tonalità di verde più scure.
Figura 8. Color.Green tint con BlendMode.Darken.

Per ulteriori informazioni sulle diverse modalità di fusione disponibili, consulta la documentazione di riferimento di BlendMode.

Applica un filtro Image con matrice di colori

Trasforma l'immagine utilizzando l'opzione ColorFilter Matrice dei colori. Ad esempio, per applicare un filtro in bianco e nero alle tue immagini, puoi utilizzare ColorMatrix e impostare la saturazione su 0f.

Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_description),
    colorFilter = ColorFilter.colorMatrix(ColorMatrix().apply { setToSaturation(0f) })
)

Un cane con un filtro in bianco e nero applicato, che rimuove tutta la saturazione del colore.
Figura 9. Matrice colore con saturazione 0 (immagine in bianco e nero).

Regolare il contrasto o la luminosità di un Image componibile

Per modificare il contrasto e la luminosità di un'immagine, puoi utilizzare ColorMatrix per modificare i valori:

val contrast = 2f // 0f..10f (1 should be default)
val brightness = -180f // -255f..255f (0 should be default)
val colorMatrix = floatArrayOf(
    contrast, 0f, 0f, 0f, brightness,
    0f, contrast, 0f, 0f, brightness,
    0f, 0f, contrast, 0f, brightness,
    0f, 0f, 0f, 1f, 0f
)
Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_description),
    colorFilter = ColorFilter.colorMatrix(ColorMatrix(colorMatrix))
)

Un cane con luminosità e contrasto aumentati, che lo rendono più vivido.
Figura 10. Luminosità e contrasto dell'immagine regolati utilizzando ColorMatrix.

Invertire i colori di un composable Image

Per invertire i colori di un'immagine, imposta ColorMatrix su Inverti colori:

val colorMatrix = floatArrayOf(
    -1f, 0f, 0f, 0f, 255f,
    0f, -1f, 0f, 0f, 255f,
    0f, 0f, -1f, 0f, 255f,
    0f, 0f, 0f, 1f, 0f
)
Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_description),
    colorFilter = ColorFilter.colorMatrix(ColorMatrix(colorMatrix))
)

Un cane con i colori invertiti, che mostra un effetto simile a un negativo.
Figura 11. Colori invertiti nell'immagine.

Sfocare un componibile Image

Per sfocare un'immagine, utilizza Modifier.blur(), fornendo radiusX e radiusY, che specificano il raggio di sfocatura in direzione orizzontale e verticale rispettivamente.

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 = 10.dp,
            edgeTreatment = BlurredEdgeTreatment(RoundedCornerShape(8.dp))
        )
)

Un cane a cui è stato applicato un forte effetto sfocatura, che lo rende indistinto e fuori fuoco.
Figura 12. BlurEffect applicata a un'immagine.

Quando sfumi Images, ti consigliamo di utilizzare BlurredEdgeTreatment(Shape) anziché BlurredEdgeTreatment.Unbounded, in quanto quest'ultimo viene utilizzato per la sfumatura di rendering arbitrari che dovrebbero essere eseguiti al di fuori dei limiti dei contenuti originali. Per le immagini, è probabile che non vengano visualizzate al di fuori dei limiti dei contenuti, mentre la sfocatura di un rettangolo arrotondato potrebbe richiedere questa distinzione.

Ad esempio, se impostiamo BlurredEdgeTreatment su Unbounded nell'immagine precedente, i bordi dell'immagine appaiono sfocati anziché nitidi:

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 = 10.dp,
            edgeTreatment = BlurredEdgeTreatment.Unbounded
        )
        .clip(RoundedCornerShape(8.dp))
)

Un'immagine sfocata di un cane, in cui la sfocatura si estende oltre i confini dell'immagine originale, rendendo i bordi sfocati.
Figura 13. BlurEdgeTreatment.Unbounded.