Dostosowywanie obrazu

Obrazy możesz dostosowywać za pomocą właściwości w Image komponowalnymcontentScale, colorFilter. Możesz też zastosować istniejące modyfikatory, aby dodać do Image różne efekty. 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. Domyślnie, jeśli nie określisz opcji contentScale, używana jest opcja ContentScale.Fit.

W poniższym przykładzie Image jest ograniczony do rozmiaru 150 dp z obramowaniem, a tło jest ustawione na żółte w przypadku Image, 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 daje różne wyniki. W wyborze odpowiedniego trybu ContentScale pomoże Ci ta tabela:

Obraz źródłowy Źródło portretu, na którym widać psa. Źródło w formacie poziomym, które przedstawia innego psa.
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. Portret psa skalowany równomiernie. Pies w jednolitej skali.
ContentScale.Crop: wyśrodkuj obraz w dostępnym miejscu. Zdjęcie portretowe przycięte tak, aby wypełniało kwadratową ramkę, pokazujące tylko środkową część obrazu. Obraz poziomy przycięty tak, aby wypełniał kwadratową ramkę, w której widać tylko środkową część obrazu.
ContentScale.FillHeight: skaluje źródło przy zachowaniu formatu obrazu, tak aby granice odpowiadały wysokości miejsca docelowego. Obraz w formacie pionowym przeskalowany tak, aby wypełniał wysokość kwadratowej ramki. Po lewej i prawej stronie widać pełny obraz z żółtym tłem. Obraz poziomy przeskalowany tak, aby wypełniał wysokość kwadratowej ramki, z przyciętymi bokami.
ContentScale.FillWidth: skaluje źródło przy zachowaniu współczynnika proporcji, tak aby granice odpowiadały szerokości miejsca docelowego. Obraz w formacie pionowym przeskalowany tak, aby wypełniał szerokość kwadratowej ramki, z przyciętą górą i dołem. Obraz poziomy przeskalowany tak, aby wypełniał szerokość kwadratowej ramki. Cały obraz jest widoczny, a u góry i u dołu widać żółte tło.
ContentScale.FillBounds: skaluje treść w pionie i poziomie nierównomiernie, aby wypełnić granice miejsca docelowego. (Uwaga: powoduje to zniekształcenie obrazów, jeśli umieścisz je w kontenerach, których format nie odpowiada formatowi obrazu). Obraz w orientacji pionowej zniekształcony tak, aby całkowicie wypełniał kwadratową ramkę, co powoduje rozciągnięcie obrazu. Obraz poziomy zniekształcony tak, aby całkowicie wypełnić kwadratową ramkę, co powoduje rozciągnięcie obrazu.
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 None. Treści zawsze będą mieścić się w granicach. Jeśli treść jest mniejsza niż granice, nie zostanie przeskalowana. Obraz źródłowy większy niż granice: Obraz w formacie pionowym, pierwotnie większy niż kwadratowe granice, został zmniejszony, aby się w nich zmieścić, przy zachowaniu współczynnika proporcji. Po bokach widać żółte tło. Obraz źródłowy mniejszy niż granice: Obraz w orientacji pionowej, pierwotnie mniejszy niż kwadratowe granice, wyświetlany w ramce w oryginalnym rozmiarze, z żółtym tłem wokół niego. Obraz źródłowy większy niż granice: Obraz panoramiczny, pierwotnie większy niż kwadratowe granice, został zmniejszony, aby się w nich zmieścić, przy zachowaniu współczynnika proporcji. U góry i u dołu widać żółte tło. Obraz źródłowy mniejszy niż granice: Obraz w orientacji poziomej, pierwotnie mniejszy niż kwadratowe granice, wyświetlany w ramce w oryginalnym rozmiarze, z żółtym tłem wokół niego.
ContentScale.None: nie stosuj skalowania do źródła. Jeśli treść jest mniejsza niż granice miejsca docelowego, nie zostanie powiększona, aby dopasować się do obszaru. Obraz źródłowy większy niż granice: Obraz w formacie pionowym, pierwotnie większy niż kwadratowe granice, wyświetlany w oryginalnym rozmiarze, z częściami wystającymi poza górną i dolną krawędź ramki. Obraz źródłowy mniejszy niż granice: Obraz w orientacji pionowej, pierwotnie mniejszy niż kwadratowe granice, wyświetlany w ramce w oryginalnym rozmiarze, z żółtym tłem wokół niego. Obraz źródłowy większy niż granice: Obraz panoramiczny, pierwotnie większy niż kwadratowe granice, wyświetlany w oryginalnym rozmiarze, z częściami wystającymi poza lewą i prawą stronę ramki. Obraz źródłowy mniejszy niż granice: Obraz w orientacji poziomej, pierwotnie mniejszy niż kwadratowe granice, wyświetlany w ramce w oryginalnym rozmiarze, z żółtym tłem wokół niego.

Przycinanie elementu 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 tego polecenia: 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)
)

Obraz psa wycięty w idealne koło.
Rysunek 1. Wycinanie obrazu za pomocą CircleShape.

W przypadku kształtu z zaokrąglonymi rogami użyj Modifier.clip(RoundedCornerShape(16.dp)), podając rozmiar 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))
)

Kwadratowe zdjęcie psa z zaokrąglonymi rogami.
Rysunek 2. Wycinanie obrazu za pomocą RoundedCornerShape.

Możesz też utworzyć własny kształt przycinania, rozszerzając Shape i podając Path, wokół którego ma być przycinany kształt:

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

Kwadratowe zdjęcie psa przycięte do niestandardowego owalnego kształtu.
Rysunek 3 Przycinanie obrazu za pomocą niestandardowego kształtu ścieżki.

Dodawanie obramowania do komponentu Image

Często wykonuje się operację łączenia 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)
)

Kwadratowe zdjęcie psa przycięte do kształtu koła z żółtą obwódką.
Rysunek 4. przyciętym obrazem z ramką,

Aby utworzyć obramowanie z gradientem, możesz użyć interfejsu Brush API do narysowania obramowania z gradientem w kolorach tęczy 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)
)

Okrągły obraz psa z tęczowym gradientem wokół okręgu.
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)
)

Kwadratowy obraz psa przekształcony do formatu 16:9, dzięki czemu jest szerszy i krótszy.
Rysunek 6. Używanie aplikacji Modifier.aspectRatio(16f/9f) na urządzeniu Image.

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

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

Zabarwianie obrazów

Użycie ColorFilter.tint(color, blendMode) powoduje zastosowanie trybu mieszania z podanym kolorem do komponentu Image. ColorFilter.tint(color, blendMode) używa BlendMode.SrcIn do barwienia treści, co oznacza, że podany kolor jest wyświetlany w miejscu, w którym obraz jest wyświetlany na ekranie. Jest to przydatne w przypadku ikon i grafiki wektorowej, które wymagają innego motywu.

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

Obraz przedstawiający autobus z nałożonym żółtym odcieniem.
Rysunek 7. Zastosowano ustawienie ColorFilter.tint z wartością 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)
)

Pies z zieloną poświatą uzyskaną za pomocą BlendMode.Darken, co daje ciemniejsze odcienie zieleni.
Rysunek 8. Color.Green tintBlendMode.Darken.

Więcej informacji o dostępnych trybach mieszania znajdziesz w BlendModedokumentacji referencyjnej.

Stosowanie filtra Image z macierzą kolorów

Przekształć obraz za pomocą opcji matrycy kolorów ColorFilter. 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) })
)

Pies z zastosowanym filtrem czarno-białym, który usuwa całe nasycenie kolorów.
Rysunek 9. Matryca kolorów z nasyceniem 0 (czarno-biały obraz).

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

Pies o zwiększonej jasności i kontraście, dzięki czemu wygląda bardziej żywo.
Rysunek 10. Dostosowano jasność i kontrast obrazu za pomocą funkcji ColorMatrix.

Odwracanie kolorów komponentu 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))
)

Pies z odwróconymi kolorami, co daje efekt negatywu.
Rysunek 11. Odwrócone kolory na obrazie.

Rozmywanie komponentu Image

Aby rozmyć obraz, użyj Modifier.blur(), podając radiusXradiusY, które określają promień rozmycia 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))
        )
)

Pies z silnym efektem rozmycia, przez co jest niewyraźny i nieostry.
Rysunek 12. BlurEffect zastosowano do obrazu.

Podczas rozmywania elementu Images zalecamy używanie elementu BlurredEdgeTreatment(Shape) zamiast BlurredEdgeTreatment.Unbounded, ponieważ ten ostatni 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 ustawimy wartość BlurredEdgeTreatment na Unbounded na poprzednim obrazie, 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))
)

Rozmyty obraz psa, w którym rozmycie wykracza poza pierwotne granice obrazu, przez co krawędzie są niewyraźne.
Rysunek 13. BlurEdgeTreatment.Unbounded.