Personalizzare un'immagine

Le immagini possono essere personalizzate utilizzando le proprietà di un componente componibile Image (contentScale, colorFilter). Puoi anche applicare l'Modifiers esistente per applicare effetti diversi al tuo Image. I modificatori possono essere utilizzati su qualsiasi elemento componibile, non solo sull'elemento componibile Image, mentre contentScale e colorFilter sono parametri espliciti dell'elemento 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, verrà 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 genererà risultati diversi. Di seguito è riportata una tabella che può aiutarti a scegliere la modalità ContentScale corretta per le tue esigenze:

Immagine di origine Immagine verticale di origine Immagine di origine orizzontale
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. ContentScale.Fit portrait ContentScale.Fit landscape
ContentScale.Crop: Centra il ritaglio dell'immagine nello spazio disponibile. ContentScale.Crop portrait ContentScale.Crop landscape
ContentScale.FillHeight: ridimensiona l'origine mantenendo le proporzioni in modo che i limiti corrispondano all'altezza della destinazione. ContentScale.FillHeight verticale ContentScale.FillHeight landscape
ContentScale.FillWidth: ridimensiona l'origine mantenendo le proporzioni in modo che i limiti corrispondano alla larghezza della destinazione. ContentScale.FillWidth verticale ContentScale.FillWidth orizzontale
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) ContentScale.FillBounds verticale ContentScale.FillBounds landscape
ContentScale.Inside: ridimensiona l'origine per mantenere le proporzioni all'interno dei limiti della destinazione. Se l'origine è più piccola o uguale alla destinazione in entrambe le dimensioni, si comporta in modo simile a "Nessuno". 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: ContentScale.Inside ritratto, immagine di origine più grande dei limiti Immagine di origine più piccola dei limiti: ContentScale.Inside ritratto, immagine di origine più piccola dei limiti 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 scalati 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

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

Ritagliare un'immagine con CircleShape
Figura 1: ritaglio di un'immagine con CircleShape

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

Ritagliare un'immagine con RoundedCornerShape
Figura 2: ritaglio di 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())
)

Ritagliare un'immagine con una forma di tracciato personalizzata
Figura 3: ritaglio di un'immagine con 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 fornire un bordo intorno
Figura 4: ritaglia un'immagine e aggiungi un bordo

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

Bordo circolare con sfumatura arcobaleno
Figura 5: bordo circolare con sfumatura arcobaleno

Impostare proporzioni personalizzate

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

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

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.

Colorare un'immagine

L'utilizzo di ColorFilter.tint(color, blendMode) applicherà 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 verrà mostrato dove l'immagine viene visualizzata sullo schermo. Questa opzione è 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)
)

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

Altri BlendMode producono effetti diversi. Ad esempio, impostando BlendMode.Darken con un Color.Green su un'immagine si ottiene 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)
)

Color.Green tint con BlendMode.Darken
Figura 8: colore.Tonalità verde con BlendMode.Darken

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

Applicazione di 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) })
)

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

Luminosità e contrasto dell'immagine regolati utilizzando ColorMatrix
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))
)

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

Sfocare un Image componibile

Per sfocare un'immagine, utilizza Modifier.blur(), fornendo radiusX e radiusY, che specificano il raggio di sfocatura rispettivamente 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))
        )
)

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

Quando sfumi Images, ti consigliamo di utilizzare BlurredEdgeTreatment(Shape) invece di 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 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