Dostosowywanie obrazu

Obrazy można dostosowywać za pomocą właściwości elementu Image z możliwością komponowania (contentScale, colorFilter). Możesz też zastosować istniejący Modifiers, aby dodać różne efekty do elementu Image. Modyfikatorów można używać w dowolnym komponencie, nie tylko w komponencie Image, natomiast contentScalecolorFilter są jawnymi parametrami komponentu Image.

Skala treści

Określ opcję contentScale, aby przyciąć obraz lub zmienić sposób jego skalowania w ramach jego granic. Jeśli nie określisz opcji contentScale, domyślnie zostanie użyta opcja ContentScale.Fit.

W przykładzie poniżej komponent Image jest ograniczony do rozmiaru 150 dp z obramowaniem, a tło komponentu Image jest ustawione na kolor żółty, aby zaprezentować różne opcje ContentScale w tabeli poniżej.

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
)

Ustawienie różnych opcji ContentScale spowoduje uzyskanie różnych wyników. Poniżej znajdziesz tabelę, która pomoże Ci wybrać odpowiedni tryb ContentScale:

Obraz źródłowy Obraz źródłowy w orientacji pionowej Obraz źródłowy w orientacji poziomej
ContentScale Wynik – obraz w orientacji pionowej: Wynik – obraz poziomy:
ContentScale.Fit: skaluj obraz równomiernie, zachowując format obrazu (domyślnie). Jeśli treść jest mniejsza niż rozmiar, obraz jest skalowany w górę, aby dopasować się do granic. ContentScale.Fit portrait ContentScale.Fit landscape
ContentScale.Crop: wyśrodkuj obraz w dostępnym miejscu. ContentScale.Crop portrait ContentScale.Crop landscape
ContentScale.FillHeight: skaluje źródło przy zachowaniu formatu obrazu, tak aby granice odpowiadały wysokości miejsca docelowego. ContentScale.FillHeight w trybie pionowym ContentScale.FillHeight w trybie poziomym
ContentScale.FillWidth: skaluje źródło przy zachowaniu współczynnika proporcji, tak aby granice odpowiadały szerokości miejsca docelowego. ContentScale.FillWidth w przypadku orientacji pionowej ContentScale.FillWidth w orientacji poziomej
ContentScale.FillBounds: skaluje treść w pionie i poziomie nierównomiernie, aby wypełnić granice miejsca docelowego. (Uwaga: spowoduje to zniekształcenie obrazów, jeśli umieścisz je w kontenerach, których format nie odpowiada formatowi obrazu). ContentScale.FillBounds w orientacji pionowej ContentScale.FillBounds w trybie poziomym
ContentScale.Inside: Skaluj źródło, aby zachować współczynnik proporcji w granicach miejsca docelowego. Jeśli źródło jest mniejsze lub równe miejscu docelowemu w obu wymiarach, zachowuje się podobnie jak wartość „Brak”. Treści będą zawsze mieścić się w granicach. Jeśli treść jest mniejsza niż granice, nie zostanie przeskalowana. Obraz źródłowy większy niż granice:ContentScale.Inside w orientacji pionowej, obraz źródłowy większy niż graniceObraz źródłowy mniejszy niż granice:ContentScale.Inside w przypadku obrazu w orientacji pionowej, obraz źródłowy mniejszy niż granice Obraz źródłowy większy niż granice:ContentScale.Inside w orientacji poziomej, obraz źródłowy większy niż graniceObraz źródłowy mniejszy niż granice:ContentScale.Inside w orientacji poziomej, obraz źródłowy mniejszy niż granice
ContentScale.None: nie stosuj skalowania do źródła. Jeśli treść jest mniejsza niż granice miejsca docelowego, nie zostanie powiększona, aby wypełnić obszar. Obraz źródłowy większy niż granice:ContentScale.None, obraz źródłowy w orientacji pionowej większy niż graniceObraz źródłowy mniejszy niż granice:ContentScale.None, obraz źródłowy w orientacji pionowej mniejszy niż granice Obraz źródłowy większy niż granice:ContentScale.None w orientacji poziomej, obraz źródłowy większy niż graniceObraz źródłowy mniejszy niż granice:ContentScale.None, obraz w orientacji poziomej, obraz źródłowy mniejszy niż granice

Przycinanie elementu kompozycyjnego Image do kształtu

Aby dopasować obraz do kształtu, użyj wbudowanego modyfikatora clip. Aby przyciąć obraz do kształtu koła, użyj ikony 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)
)

Przycinanie obrazu za pomocą elementu CircleShape
Ilustracja 1. Przycinanie obrazu za pomocą CircleShape

Kształt zaokrąglonego rogu – użyj Modifier.clip(RoundedCornerShape(16.dp)) z rozmiarem rogów, które mają być zaokrąglone:

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

Przycinanie obrazu za pomocą RoundedCornerShape
Ilustracja 2. Przycinanie obrazu za pomocą RoundedCornerShape

Możesz też utworzyć własny kształt przycinania, rozszerzając Shape i podając Path dla kształtu, wokół którego ma nastąpić przycięcie:

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

Przycinanie obrazu za pomocą niestandardowego kształtu ścieżki
Ilustracja 3. Przycinanie obrazu za pomocą niestandardowego kształtu ścieżki

Dodawanie obramowania do komponentu Image

Często stosuje się połączenie Modifier.border()Modifier.clip(), aby utworzyć ramkę wokół obrazu:

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

przyciąć obraz i dodać do niego obramowanie;
Rysunek 4. Przycinanie obrazu i dodawanie do niego obramowania

Jeśli chcesz utworzyć obramowanie z gradientem, możesz użyć interfejsu Brush API, aby narysować tęczowe obramowanie wokół obrazu:

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

Obramowanie koła z gradientem tęczowym
Rysunek 5. Obramowanie koła z gradientem w kolorach tęczy

Ustawianie niestandardowych proporcji

Aby przekształcić obraz w niestandardowy format, użyj funkcji Modifier.aspectRatio(16f/9f), aby podać niestandardowy format obrazu (lub dowolnego elementu kompozycyjnego).

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

Używanie modyfikatora Modifier.aspectRatio(16f/9f) w przypadku elementu Image
Rysunek 6. Używanie Modifier.aspectRatio(16f/9f) na obrazie

Filtr kolorów – przekształcanie kolorów pikseli obrazu

Kompozycja Image ma parametr colorFilter, który może zmieniać dane wyjściowe poszczególnych pikseli obrazu.

Barwienie obrazu

Użycie ColorFilter.tint(color, blendMode) spowoduje zastosowanie trybu mieszania z podanym kolorem do funkcji kompozycyjnej Image. ColorFilter.tint(color, blendMode) używa BlendMode.SrcIn do barwienia treści, co oznacza, że podany kolor będzie wyświetlany w miejscu, w którym obraz jest wyświetlany na ekranie. Jest to przydatne w przypadku ikon i wektorów, które muszą mieć inny motyw.

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

Zastosowano ColorFilter.tint z BlendMode.SrcIn
Rysunek 7. Zastosowanie ColorFilter.tint z BlendMode.SrcIn

Inne BlendMode wywołują różne efekty. Na przykład ustawienie BlendMode.Darken z symbolem Color.Green na obrazie daje ten wynik:

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 with BlendMode.Darken
Rysunek 8. Kolor. Zielony odcień z BlendMode.Darken

Więcej informacji o dostępnych trybach mieszania znajdziesz w dokumentacji referencyjnej dotyczącej trybu BlendMode.

Stosowanie filtra Image z macierzą kolorów

Przekształć obraz za pomocą opcji ColorFiltermatryca kolorówColorFilter. Na przykład, aby zastosować filtr czarno-biały do zdjęć, możesz użyć ColorMatrix i ustawić nasycenie na 0f.

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

Matryca kolorów z nasyceniem 0 (obraz czarno-biały)
Rysunek 9. Macierz kolorów z nasyceniem 0 (obraz czarno-biały)

Dostosowywanie kontrastu lub jasności elementu Image

Aby zmienić kontrast i jasność obrazu, możesz użyć ColorMatrix, aby zmienić wartości:

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

Dostosowana jasność i kontrast obrazu za pomocą funkcji ColorMatrix
Ilustracja 10. Dostosowana jasność i kontrast obrazu za pomocą funkcji ColorMatrix

Odwracanie kolorów funkcji kompozycyjnej Image

Aby odwrócić kolory obrazu, ustaw opcję ColorMatrix na odwrócenie kolorów:

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

Odwrócone kolory na obrazie
Rysunek 11. Odwrócone kolory na obrazie

Rozmycie funkcji kompozycyjnej Image

Aby rozmyć obraz, użyj Modifier.blur(), podając radiusXradiusY, które określają promień rozmycia odpowiednio w kierunku poziomym i pionowym.

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

Efekt rozmycia zastosowany do obrazu
Rysunek 12. Efekt rozmycia zastosowany do obrazu

Podczas rozmywania Images zalecamy używanie BlurredEdgeTreatment(Shape) zamiast BlurredEdgeTreatment.Unbounded, ponieważ ten drugi parametr służy do rozmywania dowolnych renderowań, które mają być renderowane poza granicami oryginalnych treści. W przypadku obrazów prawdopodobnie nie będą one renderowane poza granicami treści, natomiast rozmycie zaokrąglonego prostokąta może wymagać tego rozróżnienia.

Jeśli na przykład w przypadku powyższego obrazu ustawimy wartość BlurredEdgeTreatment na Nieograniczony, krawędzie obrazu będą rozmyte, a nie ostre:

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
Ilustracja 13. BlurEdgeTreatment.Unbounded