Dostosowywanie obrazu

Obrazy można dostosowywać za pomocą właściwości elementu kompozycyjnego Image (contentScale, colorFilter). Możesz też zastosować istniejący element Modifiers, aby zastosować różne efekty w elemencie Image. Modyfikatory mogą być używane w dowolnym elemencie kompozycyjnym, a nie tylko w elemencie Image kompozycyjnym, natomiast parametry contentScale i colorFilter są jawnymi parametrami funkcji kompozycyjnej Image.

Skala treści

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

W poniższym przykładzie obraz kompozycyjny jest ograniczony do rozmiaru 150 dp z obramowaniem, a tło jest ustawione na żółte w elemencie kompozycyjnym Image w celu zaprezentowania różnych ContentScale opcji z 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 danych wyjściowych. Poniższa tabela 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: równomierne skalowanie obrazu z zachowaniem współczynnika proporcji (domyślnego). Jeśli treść jest mniejsza niż rozmiar, obraz jest skalowany w górę, aby mieścił się w granicach. ContentScale.Fit – pionowa Poziomy ContentScale.Fit
ContentScale.Crop: przytnij obraz na środku, aby mieścił się w dostępnym miejscu. ContentScale.Przytnij w pionie ContentScale.Przytnij obraz w orientacji poziomej
ContentScale.FillHeight: skaluj źródło przy zachowaniu współczynnika proporcji tak, by progi były zgodne z wysokością miejsca docelowego. ContentScale.FillHeight – pionowa Poziomy ContentScale.FillHeight
ContentScale.FillWidth: skaluje źródło przy zachowaniu współczynnika proporcji w taki sposób, aby granice pasowały do szerokości docelowej. ContentScale.FillWidth (pionowa) Poziomo ContentScale.FillWidth
ContentScale.FillBounds: skaluj treść w pionie i poziomie nierównomiernie, aby wypełnić granice docelowe. (Uwaga: obrazy umieszczone w kontenerach, które nie pasują do dokładnego współczynnika proporcji), spowodują zniekształcenie. ContentScale.FillBounds – pionowa Poziomy ContentScale.FillBounds
ContentScale.Inside: przeskaluj źródło, aby zachować współczynnik proporcji w granicach docelowych. Jeśli źródło ma w obu wymiarach mniejsze lub równe miejsce docelowe, działa podobnie do opcji „Brak”. Treść zawsze mieści się w wyznaczonych granicach. Jeśli zawartość jest mniejsza niż progi, skalowanie nie zostanie zastosowane. Obraz źródłowy przekracza granicę: ContentScale.W orientacji pionowej, obraz źródłowy większy niż granice Obraz źródłowy jest mniejszy niż granice: ContentScale.W orientacji pionowej, obraz źródłowy jest mniejszy niż granice Obraz źródłowy przekracza granicę: ContentScale.W orientacji poziomej, obraz źródłowy większy niż granice Obraz źródłowy jest mniejszy niż granice: ContentScale.W orientacji poziomej, obraz źródłowy jest mniejszy niż granice
ContentScale.None: nie skaluj źródła. Jeśli zawartość jest mniejsza niż progi miejsca docelowego, nie zostanie przeskalowana w taki sposób, aby pasowała do obszaru. Obraz źródłowy przekracza granicę: ContentScale.Brak orientacji pionowej, obraz źródłowy większy niż granice Obraz źródłowy jest mniejszy niż granice: ContentScale.Brak orientacji pionowej, obraz źródłowy jest mniejszy niż granice Obraz źródłowy przekracza granicę: ContentScale.Brak poziomy, obraz źródłowy większy niż granice Obraz źródłowy jest mniejszy niż granice: ContentScale.None w orientacji poziomej, obraz źródłowy jest mniejszy niż granice

Przycinanie funkcji Image kompozycyjnej do kształtu

Aby dopasować obraz do kształtu, użyj wbudowanego modyfikatora clip. Aby przyciąć obraz do kształtu okręgu, użyj funkcji 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 Circle shape
Rys. 1. Przycinanie obrazu o kształcie okręgu

Zaokrąglony narożnik – użyj Modifier.clip(RoundedCornerShape(16.dp)) razem 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ą funkcji RoundedCorner shape
Rys. 2. Przycinanie obrazu z zaokrąglonym narożnikiem

Możesz też utworzyć własny kształt przycinania, rozszerzając Shape i podając Path, aby go przyciąć:

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 o niestandardowym kształcie ścieżki
Rys. 3. Przycinanie obrazu z niestandardowym kształtem ścieżki

Dodawanie obramowania do funkcji kompozycyjnej Image

Popularną operacją jest połączenie elementów Modifier.border() z Modifier.clip(), aby utworzyć obramowanie 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)
)

Przytnij obraz i dodaj do niego obramowanie
Rysunek 4. Przycinanie obrazu i obramowanie wokół niego

Jeśli chcesz utworzyć obramowanie w postaci gradientu, możesz za pomocą interfejsu API Brush narysować tęczowe obramowanie gradientowe 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)
)

Ramka okręgu z tęczowym gradientem
Rysunek 5. Obramowanie okręgu z tęczowym gradientem

Ustaw niestandardowy format obrazu

Aby przekształcić obraz w niestandardowy format obrazu, użyj funkcji Modifier.aspectRatio(16f/9f), aby określić format niestandardowy dla 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życie modyfikatora.aspectRatio(16f/9f) do obrazu
Rysunek 6. Użycie elementu Modifier.aspectRatio(16f/9f) w 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 właściwości ColorFilter.tint(color, blendMode) spowoduje zastosowanie trybu mieszania z podanym kolorem do funkcji kompozycyjnej Image. ColorFilter.tint(color, blendMode) używa funkcji BlendMode.SrcIn do zabarwienia treści, co oznacza, że wybrany kolor będzie widoczny tam, gdzie 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 filtr ColorFilter.tint za pomocą funkcji BlendMode.SrcIn
Rysunek 7. Zastosowanie parametru ColorFilter.tint za pomocą funkcji BlendMode.SrcIn

Inne wyniki (BlendMode) mają inne efekty. Na przykład ustawienie BlendMode.Darken z elementem Color.Green na obrazie daje 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)
)

Kolor.Odcień zielony z trybem mieszania.Ściemnij
Rysunek 8.Odcień zielony z ustawieniem BlendMode.Darken

Więcej informacji o różnych dostępnych trybach mieszania znajdziesz w dokumentacji referencyjnej BlendMode.

Stosuję filtr Image z matrycą kolorów

Przekształć obraz, korzystając z opcji matryca kolorów ColorFilter. Aby na przykład zastosować do zdjęć czarno-biały filtr, użyj właściwości ColorMatrix i ustaw 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.: Matryca kolorów z nasyceniem 0 (obraz czarno-biały)

Dostosowywanie kontrastu lub jasności elementu kompozycyjnego Image

Aby zmienić kontrast i jasność obrazu, możesz użyć przycisku ColorMatrix i 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))
)

Jasność i kontrast obrazu zostały skorygowane za pomocą matrycy kolorów
Rys. 10. Korekta jasności i kontrastu obrazu przy użyciu interfejsu ColorMatrix

Odwróć kolory funkcji kompozycyjnej Image

Aby odwrócić kolory obrazu, ustaw przełącznik ColorMatrix w celu odwrócenia 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 elementu kompozycyjnego Image

Aby rozmyć zdjęcie, użyj funkcji Modifier.blur(), podając wartości radiusX i radiusY, 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))
        )
)

Do obrazu zastosowano efekt rozmycia
Rysunek 12. Do obrazu zastosowano efekt rozmycia

Do rozmycia obrazu Images zaleca się użycie właściwości BlurredEdgeTreatment(Shape) zamiast BlurredEdgeTreatment.Unbounded, ponieważ służy ona do zamazywania arbitralnych renderowań, które powinny renderować się poza granicami oryginalnej treści. Obrazy prawdopodobnie nie będą renderowane poza granicami treści, natomiast rozmycie zaokrąglonego prostokąta może wymagać takiego rozróżnienia.

Jeśli na przykład w tym obrazie ustawimy 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))
)

Rozmycie.Bez ograniczeń
Ilustracja 13: Rozmycie.Bez ograniczeń