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. Zmienników można używać w dowolnym kompozytowanym komponencie, a nie tylko w komponencie Image, podczas gdy contentScalecolorFilter są jawnymi parametrami komponentu 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 przykładzie poniżej komponent Image jest ograniczony do rozmiaru 150 dp z ramką, a tło w komponencie Image ma kolor żółty, aby zademonstrować 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 jednolity sposób przy zachowaniu formatu (wartość domyślna). Jeśli zawartość jest mniejsza niż rozmiar, obraz jest powiększony, aby pasował do ramki. ContentScale.Fit portrait ContentScale.Fit landscape
ContentScale.Crop: wyśrodkuj obraz w dostępnej przestrzeni. 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 w pionie ContentScale.FillWidth landscape
ContentScale.FillBounds: skaluj treści w pionie i poziomie niejednolicie, 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 treści są mniejsze niż granice, nie zostaną one powiększone. Ź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 portrait, source image smaller than bounds Źródłowy obraz większy niż granice: ContentScale.Inside landscape, source image larger than bounds Ź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 obszaru, nie zostanie powiększona, aby pasowała do tego obszaru. Źródłowy obraz większy niż granice: ContentScale.None portrait, source image larger than bounds Źródłowy obraz mniejszy niż granice: ContentScale.None portrait, source image smaller than bounds Źródłowy obraz większy niż granice: ContentScale.None, orientacja pozioma, obraz źródłowy większy niż granice Źródłowy obraz mniejszy niż granice: ContentScale.None, orientacja pozioma, 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 obrazu za pomocą narzędzia CircleShape
Rysunek 1. Przycinanie obrazu za pomocą kształtu koła

Kształt zaokrąglonych rogów – użyj Modifier.clip(RoundedCornerShape(16.dp)) z rozmiarem rogó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 obrazu za pomocą kształtu zaokrąglonego

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()Modifier.clip(), aby utworzyć obramowanie 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 obraz i dodaj do niego obramowanie
Rysunek 4. Przytnij obraz i dodaj do niego ramkę

Jeśli chcesz utworzyć gradientową ramkę, możesz użyć interfejsu API Brush, aby narysować wokół obrazu tęczę:

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

Tęczowy gradient na obwodzie
Rysunek 5. Ramka koła z tęczowym gradientem

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 – zmienia kolory pikseli obrazu.

Składnik Image ma parametr colorFilter, który może zmienić wynik poszczególnych pikseli obrazu.

Tonowanie obrazu

Użycie ColorFilter.tint(color, blendMode) spowoduje zastosowanie trybu mieszania z danym kolorem do kompozytu Image. ColorFilter.tint(color, blendMode)używa BlendMode.SrcIn do zabarwiania treści, co oznacza, że podany kolor będzie wyświetlany w miejscach, w których obraz jest widoczny na ekranie. Jest to przydatne w przypadku ikon i wektorów, które wymagają zastosowania różnych motywów.

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. Kolorowy odcień zielony z trybem mieszania ciemnienia

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ć narzędzia 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)

Dostosowywanie kontrastu lub jasności Image komponentu

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

Rozmycie funkcji kompozytowej 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

Podczas rozmywania Images zalecamy użycie BlurredEdgeTreatment(Shape) zamiast BlurredEdgeTreatment.Unbounded, ponieważ ta druga funkcja służy do rozmywania dowolnych renderowań, które mają być renderowane poza granice oryginalnych treści. Obrazy prawdopodobnie nie będą renderowane poza granice treści, natomiast rozmycie zaokrąglonego prostokąta może wymagać takiego 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. BlurEdgeTreatment.Unbounded