Dostosowywanie obrazu

Obrazy można dostosowywać za pomocą właściwości w komponencie Image (contentScale, colorFilter). Możesz też zastosować istniejące Modifiers, aby dodać do Image różne efekty. Modyfikatory można używać w dowolnej funkcji kompozycyjnej, a nie tylko w funkcji kompozycyjnej Image, natomiast contentScale i colorFilter to jawne parametry w możliwości kompozycyjnej Image.

Skala treści

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

W poniższym przykładzie funkcja kompozycyjnej obrazu ma rozmiar 150 dp z obramowaniem, a tło w komponencie Image jest ustawione na żółte, co pozwala 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 znajduje się tabela, która pomoże Ci wybrać odpowiedni tryb ContentScale:

Obraz źródłowy Pionowy obraz źródłowy Obraz źródłowy w orientacji poziomej
ContentScale Wynik – obraz pionowy: Wynik – obraz poziomy:
ContentScale.Fit: skalowanie obrazu w taki sposób, aby zachować jego format (ustawienie domyślne). Jeśli treść jest mniejsza, obraz zostanie przeskalowany w górę, by mieścił się w granicach. ContentScale.Fit portrait ContentScale.Fit landscape
ContentScale.Crop: przytnij obraz do środka i przytnij go do dostępnego miejsca. ContentScale.Crop portrait ContentScale.Crop landscape
ContentScale.FillHeight: skaluj źródło, zachowując współczynnik proporcji, tak aby granice pasowały do wysokości docelowej. ContentScale.FillHeight portrait ContentScale.FillHeight poziomy
ContentScale.FillWidth: skaluj źródło, zachowując współczynnik proporcji, tak aby granice pasowały do szerokości docelowej. ContentScale.FillWidth (orientacja pionowa) ContentScale.FillWidth landscape
ContentScale.FillBounds: skaluj treści w pionie i poziomie nierównomiernie, aby wypełnić granice miejsca docelowego. (Uwaga: jeśli umieścisz je w kontenerach, które nie pasują do dokładnego współczynnika proporcji obrazu, zostaną one zniekształcone). ContentScale.FillBounds w pionie ContentScale.FillBounds w układaniu poziomym
ContentScale.Inside: skalowanie źródła w celu zachowania współczynnika proporcji w granicach docelowych. Jeśli źródło jest mniejsze lub równe docelowi w obu wymiarach, działa podobnie jak opcja „Brak”. Treści zawsze będą się mieścić w ramach. Jeśli zawartość jest mniejsza niż dopuszczalny rozmiar, skalowanie nie jest stosowane. Źródłowy obraz większy niż granice: ContentScale.Inside portrait, source image larger than bounds Źródłowy obraz mniejszy niż granice: ContentScale.Inside portret, obraz źródłowy mniejszy niż granica Źródłowy obraz większy niż granice: ContentScale.Inside poziomy, obraz źródłowy większy niż określony Źródłowy obraz mniejszy niż granice: ContentScale.Inside landscape, source image smaller than bounds
ContentScale.None: nie stosuj żadnego skalowania do źródła. Jeśli treść jest mniejsza niż granice docelowego miejsca, nie zostanie powiększona, aby pasowała do obszaru. Źródłowy obraz większy niż granice: ContentScale.None pionowo, obraz źródłowy większy niż granica Źródłowy obraz mniejszy niż granice: ContentScale.Brak w orientacji pionowej, obraz źródłowy mniejszy niż granica Źródłowy obraz większy niż granice: ContentScale.None w orientacji poziomej, obraz źródłowy większy niż granice Źródłowy obraz mniejszy niż granice: ContentScale.None w orientacji poziomej, obraz źródłowy mniejszy niż granice

Przycinanie kompozytowego 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 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 zdjęcia za pomocą obiektu CircleCircle
Rysunek 1. Przycinanie obrazu za pomocą kształtu koła

Zaokrąglony narożnik (użyj Modifier.clip(RoundedCornerShape(16.dp)) z rozmiarem narożników, które chcesz zaokrąglić:

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ą kształtu zaokrąglonego
Rysunek 2. Przycinanie zdjęcia za pomocą rozszerzenia RoundedCorner shape

Możesz też utworzyć własny kształt przycinania, rozszerzając element Shape i podając element Path, do 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())
)

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

Typową operacją jest połączenie Modifier.border() i Modifier.clip() w celu utworzenia obramowania 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)
)

Przytnij zdjęcie i dodaj do niego obramowanie
Rysunek 4. Przycinanie obrazu i dodawanie do niego obramowania

Jeśli chcesz utworzyć gradientową ramkę, możesz użyć interfejsu API Brush, aby narysować tęczę na krawędzi 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ęczy
Rysunek 5. Tęczowe obramowanie gradientu

Ustawianie niestandardowych proporcji

Aby przekształcić obraz w niestandardowy format obrazu, użyj opcji Modifier.aspectRatio(16f/9f), aby podać niestandardowy format obrazu (lub dowolny komponent).

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

Użycie funkcji Modifier.aspectRatio(16f/9f) na obiekcie Image
Rysunek 6. Używanie funkcji Modifier.aspectRatio(16f/9f) na obrazie

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

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

Przyciemnianie obrazu

Użycie ColorFilter.tint(color, blendMode) spowoduje zastosowanie trybu mieszania z danym kolorem do komponentu 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 widoczny na ekranie. Jest to przydatne w przypadku ikon i wektorów, 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)
)

Efekt ColorFilter.tint zastosowany za pomocą BlendMode.SrcIn
Rysunek 7. Filtr kolorów.tint zastosowany za pomocą BlendMode.SrcIn

Inne BlendMode mają inne skutki. Na przykład ustawienie wartości BlendMode.Darken z wartością Color.Green na obrazie spowoduje taki wynik:

Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_description),
    colorFilter = ColorFilter.tint(Color.Green, blendMode = BlendMode.Darken)
)

Odcień koloru zielony z BlendMode.Zaciemnienie
Rysunek 8.: Kolor.Zielony odcień z funkcją BlendMode.Darken

Więcej informacji o dostępnych trybach mieszania znajdziesz w dokumentacji na temat BlendMode.

Stosowanie filtra Image z macierzą kolorów

Przekształć obraz za pomocą opcji matrycy kolorów ColorFilter. Aby na przykład zastosować filtr czarno-biały, możesz użyć opcji 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 nasycenie 0 (obraz czarno-biały)
Rysunek 9. Macierz kolorów z nasycenie 0 (obraz czarno-biały)

Dostosuj kontrast i jasność elementu kompozycyjnego 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))
)

Zmieniona jasność i kontrast obrazu za pomocą funkcji ColorMatrix
Rysunek 10. Zmodyfikowana jasność i kontrast obrazu za pomocą narzędzia ColorMatrix

Odwracanie kolorów w komponowalnym elemencie Image

Aby odwrócić kolory obrazu, ustaw ColorMatrix, aby odwrócić kolory:

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

Rozmyj element kompozycyjny Image

Aby rozmyć obraz, użyj tagu Modifier.blur(), podając wartości radiusX i radiusY, które określają odpowiednio promień rozmycie 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 zdjęcia

Do zamazywania właściwości Images zalecamy użycie właściwości BlurredEdgeTreatment(Shape) zamiast BlurredEdgeTreatment.Unbounded, ponieważ ta druga opcja służy do zamazywania dowolnych renderowania, które powinny wyrenderować się poza granicami oryginalnej treści. W przypadku obrazów prawdopodobnie nie zostaną one wyrenderowane poza granicami treści, a rozmycie zaokrąglonego prostokąta może wymagać tego rozróżnienia.

Jeśli na przykład na powyższym obrazie ustawimy wartość BlurredEdgeTreatment na „Bez ograniczeń”, 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
Rysunek 13. Efekt zamazywania. Bez ograniczenia