Personalizzare un'immagine

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

Scala dei contenuti

Specifica un'opzione contentScale per ritagliare o modificare il ridimensionamento di un'immagine all'interno dei suoi limiti. Per impostazione predefinita, se non specifichi un'opzione contentScale, verrà utilizzato ContentScale.Fit.

Nell'esempio seguente, il composable immagine è limitato a una dimensione di 150 dp con un bordino 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 opzioni ContentScale diverse comporterà risultati diversi. Di seguito è riportata una tabella che può aiutarti a scegliere la modalità ContentScale corretta di cui hai bisogno:

Immagine di origine Immagine di origine verticale Immagine di origine orizzontale
ContentScale Risultato: immagine verticale: Risultato: immagine orizzontale:
ContentScale.Fit: ridimensiona l'immagine in modo uniforme, mantenendo le proporzioni (valore predefinito). Se i contenuti sono più piccoli delle dimensioni, l'immagine viene aumentata di dimensioni per adattarsi ai limiti. ContentScale.Fit portrait ContentScale.Fit landscape
ContentScale.Crop: ritaglia l'immagine al centro dello spazio disponibile. ContentScale.Crop portrait ContentScale.Crop landscape
ContentScale.FillHeight: scala l'origine mantenendo le proporzioni in modo che i limiti corrispondano all'altezza di destinazione. Ritratto ContentScale.FillHeight Orizzontale ContentScale.FillHeight
ContentScale.FillWidth: ridimensiona l'origine mantenendo le proporzioni in modo che i limiti corrispondano alla larghezza della destinazione. Ritratto ContentScale.FillWidth Orizzontale ContentScale.FillWidth
ContentScale.FillBounds: ridimensiona i contenuti verticalmente e orizzontalmente in modo non uniforme per riempire i limiti della destinazione. (Nota: le immagini verranno distorte se le inserisci in contenitori che non corrispondono alle proporzioni esatte dell'immagine) Ritratto ContentScale.FillBounds Orizzontale ContentScale.FillBounds
ContentScale.Inside: ridimensiona l'origine per mantenere le proporzioni all'interno dei limiti di destinazione. Se l'origine è minore o uguale alla destinazione in entrambe le dimensioni, si comporta in modo simile a "Nessuna". I contenuti saranno sempre contenuti nei limiti. Se i contenuti sono più piccoli dei limiti, non verrà applicata alcuna scala. Immagine di origine più grande dei limiti: ContentScale.Inside portrait, source image larger than bounds Immagine di origine più piccola dei limiti: ContentScale.Inside portrait, source image smaller than bounds Immagine di origine più grande dei limiti: ContentScale.Inside landscape, source image larger than bounds Immagine di origine più piccola dei limiti: ContentScale.Inside landscape, source image smaller than bounds
ContentScale.None: non applicare alcuna scalatura all'origine. Se i contenuti sono più piccoli dei limiti di destinazione, non verranno aumentati di dimensioni per adattarsi all'area. Immagine di origine più grande dei limiti: ContentScale.None verticale, immagine di origine più grande dei limiti Immagine di origine più piccola dei limiti: ContentScale.None verticale, immagine di origine più piccola dei limiti Immagine di origine più grande dei limiti: ContentScale.None orizzontale, immagine di origine più grande dei limiti Immagine di origine più piccola dei limiti: ContentScale.None orizzontale, immagine di origine più piccola dei limiti

Clippare un componibile Image a 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)
)

Tagliare un'immagine con la forma circolare
Figura 1: ritaglio di un'immagine con la forma circolare

Forma con angoli arrotondati: utilizza Modifier.clip(RoundedCornerShape(16.dp)) con le dimensioni degli angoli da 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))
)

Tagliare un'immagine con RoundedCornerShape
Figura 2: ritaglio di un'immagine con RoundedCornerShape

Puoi anche creare la tua forma di ritaglio estendendo Shape e specificando 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())
)

Tagliare un'immagine con una forma del percorso personalizzata
Figura 3: ritaglio di un'immagine con una forma del percorso personalizzata

Aggiungere un bordo a un composable Image

Un'operazione comune è 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)
)

Ritagliare un'immagine e applicare un bordo
Figura 4: ritaglia un'immagine e applica un bordo

Se vuoi creare un bordo sfumato, puoi utilizzare l'API Brush per disegnare un bordo sfumato arcobaleno attorno 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)
)

Bordo cerchio con sfumatura arcobaleno
Figura 5: bordo di un cerchio con sfumatura arcobaleno

Impostare proporzioni personalizzate

Per trasformare un'immagine in proporzioni personalizzate, utilizza Modifier.aspectRatio(16f/9f) per specificare un'opzione personalizzata per un'immagine (o per qualsiasi composibile).

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

Utilizzo di Modifier.aspectRatio(16f/9f) su Image
Figura 6: utilizzo di Modifier.aspectRatio(16f/9f) sull'immagine

Filtro colore: trasforma i colori dei pixel dell'immagine

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

Colorare un'immagine

L'utilizzo di ColorFilter.tint(color, blendMode) applica una modalità di miscela 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 verrà visualizzato dove l'immagine viene visualizzata sullo schermo. Questa opzione è utile per le icone e i 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)
)

ColorFilter.tint applicato con BlendMode.SrcIn
Figura 7: ColorFilter.tint applicato con BlendMode.SrcIn

Altri BlendMode hanno effetti diversi. Ad esempio, impostareBlendMode.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)
)

Tinta Color.Green con BlendMode.Darken
Figura 8: Color.Verde con BlendMode.Scurisci

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

Applicazione di un filtro Image con matrice di colori

Trasforma l'immagine utilizzando l'opzione della matrice dei colori ColorFilter. Ad esempio, per applicare un filtro in bianco e nero alle 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) })
)

Matrice dei colori con saturazione 0 (immagine in bianco e nero)
Figura 9: matrice di colori con saturazione 0 (immagine in bianco e nero)

Regolare il contrasto o la luminosità di un componibile Image

Per modificare il contrasto e la luminosità di un'immagine, puoi utilizzare il pulsante 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))
)

Luminosità e contrasto dell'immagine regolati utilizzando ColorMatrix
Figura 10: luminosità e contrasto dell'immagine regolati utilizzando ColorMatrix

Inverti i colori di un composable Image

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

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))
)

Colori invertiti nell'immagine
Figura 11: colori invertiti nell'immagine

Sfocare un componibile Image

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

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))
        )
)

Effetto sfocatura applicato all'immagine
Figura 12: BlurEffect applicato all'immagine

Quando sfochi Images, ti consigliamo di utilizzare BlurredEdgeTreatment(Shape) anziché BlurredEdgeTreatment.Unbounded, poiché quest'ultimo viene utilizzato per sfocare rappresentazioni arbitrarie che dovrebbero essere visualizzate al di fuori dei confini dei contenuti originali. Per le immagini, è probabile che il rendering non venga eseguito al di fuori dei confini dei contenuti, mentre per sfocare un rettangolo arrotondato potrebbe essere necessaria questa distinzione.

Ad esempio, se impostiamo BlurredEdgeTreatment su Senza limiti nell'immagine sopra, 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))
)

BlurEdgeTreatment.Unbounded
Figura 13: BlurEdgeTreatment.Unbounded