Personalizzare un'immagine

Le immagini possono essere personalizzate utilizzando le proprietà di un componibile Image (contentScale, colorFilter). Puoi anche applicare la proprietà Modifiers esistente per applicare effetti diversi a Image. I modificatori possono essere utilizzati in qualsiasi elemento componibile, non solo in Image, mentre contentScale e colorFilter sono parametri espliciti nell'elemento componibile Image.

Scala di contenuti

Specifica un'opzione contentScale per ritagliare o modificare il modo in cui un'immagine viene ridimensionata entro i limiti. Per impostazione predefinita, se non specifichi un'opzione contentScale, verrà utilizzato ContentScale.Fit.

Nell'esempio seguente, la dimensione dell'immagine componibile è limitata a 150 dp con un bordo e lo sfondo è impostato su giallo nell'elemento componibile Image per mostrare le diverse opzioni di 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à output 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 Orizzontale immagine di origine
ContentScale Risultato - Immagine verticale: Risultato - Immagine orizzontale:
ContentScale.Fit: ridimensiona l'immagine in modo uniforme, mantenendo le proporzioni (valore predefinito). Se i contenuti sono di dimensioni inferiori, l'immagine viene ingrandita per adattarsi ai limiti. Verticale ContentScale.Fit Orizzontale ContentScale.Fit
ContentScale.Crop: ritaglia al centro l'immagine nello spazio disponibile. ContentScale.Ritaglia verticale ContentScale.Ritaglia orizzontale
ContentScale.FillHeight: ridimensiona l'origine mantenendo le proporzioni in modo che i limiti corrispondano all'altezza della destinazione. Verticale ContentScale.FillHeight Orizzontale ContentScale.FillHeight
ContentScale.FillWidth: ridimensiona l'origine mantenendo le proporzioni in modo che i limiti corrispondano alla larghezza della destinazione. Verticale ContentScale.FillLarghezza Orizzontale ContentScale.FillLarghezza
ContentScale.FillBounds: ridimensiona i contenuti in verticale e in orizzontale in modo non uniforme per riempire i limiti della destinazione. Nota: le immagini verranno distorte se inserite in contenitori che non corrispondono alle proporzioni esatte dell'immagine. Ritratto ContentScale.FillBounds Paesaggio ContentScale.FillBounds
ContentScale.Inside: scala l'origine per mantenere le proporzioni all'interno dei limiti della destinazione. Se l'origine è inferiore 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 il contenuto è inferiore ai limiti, non verrà applicato alcun ridimensionamento. Immagine di origine più grande dei limiti: ContentScale.In verticale, immagine di origine più grande dei limiti Immagine di origine più piccola dei limiti: ContentScale.In verticale, immagine di origine più piccola dei limiti Immagine di origine più grande dei limiti: ContentScale.All'interno del paesaggio, immagine di origine più grande dei limiti Immagine di origine più piccola dei limiti: ContentScale.In orizzontale, immagine di origine più piccola dei limiti
ContentScale.None: non applicare scalabilità all'origine. Se il contenuto è inferiore ai limiti di destinazione, non verrà ridimensionato per adattarsi all'area. Immagine di origine più grande dei limiti: ContentScale.Nessuno verticale, immagine di origine più grande dei limiti Immagine di origine più piccola dei limiti: ContentScale.Nessuno verticale, immagine di origine inferiore ai limiti Immagine di origine più grande dei limiti: ContentScale.Nessuna immagine orizzontale, immagine di origine superiore ai limiti Immagine di origine più piccola dei limiti: ContentScale.Nessuna immagine orizzontale, immagine di origine inferiore ai limiti

Fissa un componibile Image a una forma

Per adattare un'immagine a una forma, usa 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)
)

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

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

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

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

Aggiungi un bordo a un componibile 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)
)

Ritaglia un'immagine e fornisci un bordo intorno
Figura 4: ritagliare un'immagine e applicare un bordo

Se vuoi creare un bordo sfumatura arcobaleno, puoi usare l'API Brush per disegnare un bordo gradiente 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 cerchio sfumato arcobaleno
Figura 5: bordo cerchio gradiente arcobaleno

Imposta proporzioni personalizzate

Per trasformare un'immagine in proporzioni personalizzate, usa Modifier.aspectRatio(16f/9f) per fornire proporzioni personalizzate per un'immagine (o per qualsiasi componibile per quell'elemento).

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

Usare Modifier.aspect ratio(16f/9f) sull'immagine
Figura 6: utilizzo di Modifier.aspectRatio(16f/9f) sull'immagine

Filtro colore: trasforma i colori dei pixel dell'immagine

L'immagine componibile 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 componibile Image. ColorFilter.tint(color, blendMode) utilizza BlendMode.SrcIn per colorare i contenuti, il che significa che verrà mostrato il colore fornito nell'immagine visualizzata sullo schermo. È utile per le icone e i vettori che devono avere un tema diverso.

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 effetti di BlendMode hanno effetti diversi. Ad esempio, l'impostazione di BlendMode.Darken con 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)
)

Colore.Tinta verde con BlendMode.Scurisci
Figura 8: tinta Color.Verde con BlendMode.Darken

Consulta la documentazione di riferimento di BlendMode per ulteriori informazioni sulle diverse modalità di fusione disponibili.

Applicazione di un filtro Image con matrice dei colori

Trasforma la tua immagine utilizzando l'opzione della matrice dei colori ColorFilter. Ad esempio, per applicare un filtro 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 di colori con saturazione 0 (immagine in bianco e nero)
Figura 9: matrice dei colori con saturazione 0 (immagine in bianco e nero)

Regola il contrasto o la luminosità di un componibile Image

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

Regolazione della luminosità e del contrasto dell'immagine utilizzando ColorMatrix
Figura 10: regolazione della luminosità e del contrasto dell'immagine utilizzando ColorMatrix

Inverti i colori di un componibile Image

Per invertire i colori di un'immagine, imposta ColorMatrix in modo da invertire i 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

Sfoca un componibile Image

Per sfocare un'immagine, usa Modifier.blur(), specificando 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: effetto di sfocatura applicato all'immagine

Quando esegui la sfocatura Images, ti consigliamo di utilizzare BlurredEdgeTreatment(Shape), anziché BlurredEdgeTreatment.Unbounded, poiché quest'ultimo viene utilizzato per la sfocatura di rendering arbitrari che si prevede vengano visualizzati 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 può richiedere questa distinzione.

Ad esempio, se impostiamo il valore BlurredEdgeTreatment su Non limitato nell'immagine sopra, i bordi dell'immagine appaiono sfocati e non più 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))
)

Sfocare i bordi.Illimitati
Figura 13: sfocaturaEdgeTreatment.Unbounded