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 in qualsiasi Componibile, non solo il componibile Image, mentre contentScale e colorFilter sono parametri espliciti nel componibile Image.

Scala dei contenuti

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

Nell'esempio riportato di seguito, la dimensione dell'immagine componibile è limitata a 150 dp con un bordo e lo sfondo è impostato sul giallo nel componibile Image per mettere in evidenza 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 produrrà 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 (impostazione predefinita). Se i contenuti sono più piccoli delle dimensioni, l'immagine viene aumentata di dimensioni per adattarsi ai limiti. ContentScale.Fit (verticale) Orizzontale ContentScale.Fit
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: scala 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 entro i limiti. Se i contenuti sono più piccoli dei limiti, non verrà applicata alcuna scala. Immagine di origine più grande dei limiti: ContentScale.Inside portrait, immagine di origine più grande dei limiti 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, immagine di origine più piccola dei limiti
ContentScale.None: non applicare alcuna scalabilità all'origine. Se i contenuti sono inferiori ai limiti di destinazione, non verranno ridimensionati 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

Clip di un componibile Image su una forma

Per adattare un'immagine a una forma, utilizza il modificatore clip integrato. Per ritagliare un'immagine in forma circolare, usa 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 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))
)

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

Ritaglia un'immagine e aggiungi un bordo intorno
Figura 4: ritagliare un'immagine e aggiungere un bordo

Se vuoi creare un bordo sfumato, puoi utilizzare l'API Brush per disegnare un bordo con sfumatura 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 del cerchio con gradiente arcobaleno

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

Uso di Modifier.aspectRatio(16f/9f) sull’immagine
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.

Colorazione di 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, in questo modo il colore fornito sarà e mostrare l'immagine sullo schermo. È utile per icone e vettori che devono essere tematizzati in modo 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: applicazione di ColorFilter.tint con MergeMode.SrcIn

Gli altri BlendMode generano effetti diversi. Ad esempio, l'impostazione BlendMode.Darken con Color.Green su un'immagine produce quanto segue 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 con BlendMode.Darken
Figura 8: Colore.Tinta verde con MergeMode.Darken

Per ulteriori informazioni, consulta la documentazione di riferimento di MergeMode sulla diverse modalità di fusione disponibili.

Applicazione di un filtro Image con matrice di colori

Trasforma la tua immagine utilizzando l'opzione Matrice dei colori ColorFilter. Ad esempio: per applicare un filtro in bianco e nero alle immagini, puoi utilizzare ColorMatrix e imposta 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)

Regola il contrasto o la luminosità di un componibile in 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))
)

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

Inverti i colori di un componibile Image

Per invertire i colori di un'immagine, imposta ColorMatrix in modo che la 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 nell'immagine
Figura 11: colori invertiti dell'immagine

Sfoca 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: effetto sfocatura applicato all'immagine

Quando sfochi Images, si consiglia di usare BlurredEdgeTreatment(Shape), invece di BlurredEdgeTreatment.Unbounded, che quest'ultimo viene utilizzato per la sfocatura di rendering arbitrari che si prevede vengano visualizzati al di fuori dei limiti del contenuti originali. È probabile che le immagini non vengano visualizzate al di fuori limiti dei contenuti; mentre per sfocare un rettangolo arrotondato può essere necessario la distinzione.

Ad esempio, se impostiamo BlurredEdgeTreatment su Illimitato nella parte precedente immagine, 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: BLUBTREdgeTreatment.Unbounded