Menyesuaikan gambar

Gambar dapat disesuaikan menggunakan properti pada composable Image (contentScale, colorFilter). Anda juga dapat menerapkan Modifiers yang ada untuk menerapkan efek yang berbeda ke Image. Pengubah dapat digunakan pada composable mana pun, bukan hanya composable Image, sedangkan contentScale dan colorFilter adalah parameter eksplisit pada composable Image.

Skala konten

Tentukan opsi contentScale untuk memangkas atau mengubah cara gambar diskalakan di dalam batasnya. Secara default, jika Anda tidak menentukan opsi contentScale, ContentScale.Fit akan digunakan.

Pada contoh di bawah, Composable gambar dibatasi hingga ukuran 150 dp dengan batas dan latar belakang disetel ke kuning pada composable Image untuk menampilkan berbagai opsi ContentScale pada tabel di bawah.

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
)

Menyetel opsi ContentScale yang berbeda akan menghasilkan output yang berbeda. Berikut adalah tabel yang dapat membantu dalam memilih mode ContentScale yang benar yang Anda butuhkan:

Gambar sumber Gambar sumber potret Gambar sumber lanskap
ContentScale Hasil - Gambar Potret: Hasil - Gambar Lanskap:
ContentScale.Fit: Menskalakan gambar secara seragam, dengan tetap mempertahankan rasio aspek (default). Jika konten lebih kecil dari ukuran, skala gambar akan ditingkatkan agar sesuai dengan batas. Potret ContentScale.Fit Lanskap ContentScale.Fit
ContentScale.Crop: Memangkas tengah gambar ke ruang yang tersedia. Potret ContentScale.Crop Lanskap ContentScale.Crop
ContentScale.FillHeight: Menskalakan sumber yang mempertahankan rasio aspek sehingga batas cocok dengan tinggi tujuan. Potret ContentScale.FillHeight Lanskap ContentScale.FillHeight
ContentScale.FillWidth: Menskalakan sumber yang mempertahankan rasio aspek agar batas cocok dengan lebar tujuan. Potret ContentScale.FillWidth Lanskap ContentScale.FillWidth
ContentScale.FillBounds: Menskalakan konten secara vertikal dan horizontal secara tidak seragam untuk mengisi batas tujuan. (Catatan: Ini akan mendistorsi gambar jika Anda meletakkannya dalam penampung yang tidak sama persis dengan rasio gambar) Potret ContentScale.FillBounds Lanskap ContentScale.FillBounds
ContentScale.Inside: Menskalakan sumber untuk mempertahankan rasio aspek di dalam batas tujuan. Jika sumbernya lebih kecil dari atau sama dengan tujuan di kedua dimensi, mode ini akan berperilaku serupa dengan `None` (Tidak ada). Konten akan selalu berada dalam batas tersebut. Jika konten lebih kecil dari batas, tidak ada penskalaan yang akan diterapkan. Gambar sumber lebih besar dari batas: Potret ContentScale.Inside, gambar sumber lebih besar dari batas Gambar sumber lebih kecil dari batas: Potret ContentScale.Inside, gambar sumber lebih kecil dari batas Gambar sumber lebih besar dari batas: Lanskap ContentScale.Inside, gambar sumber lebih besar dari batas Gambar sumber lebih kecil dari batas: Lanskap ContentScale.Inside, gambar sumber lebih kecil dari batas
ContentScale.None: Jangan terapkan penskalaan apa pun ke sumber. Jika konten lebih kecil dari batas tujuan, konten tidak akan ditingkatkan skalanya agar sesuai dengan area tersebut. Gambar sumber lebih besar dari batas: Potret ContentScale.None, gambar sumber lebih besar dari batas Gambar sumber lebih kecil dari batas: Potret ContentScale.None, gambar sumber lebih kecil dari batas Gambar sumber lebih besar dari batas: Lanskap ContentScale.None, gambar sumber lebih besar dari batas Gambar sumber lebih kecil dari batas: Lanskap ContentScale.None, gambar sumber lebih kecil dari batas

Memotong composable Image ke sebuah bentuk

Agar gambar sesuai dengan bentuk, gunakan pengubah clip bawaan. Untuk memangkas gambar menjadi bentuk lingkaran, gunakan 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)
)

Memotong gambar dengan CircleShape
Gambar 1: Memotong gambar dengan CircleShape

Bentuk sudut bulat - gunakan Modifier.clip(RoundedCornerShape(16.dp)) dengan ukuran sudut yang ingin dibulatkan:

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

Memotong gambar dengan RoundedCornerShape
Gambar 2: Memotong gambar dengan RoundedCornerShape

Anda juga dapat membuat bentuk pemotongan sendiri dengan memperluas Shape, dan memberikan Path untuk bentuk yang akan dipotong:

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

Memotong gambar dengan bentuk jalur kustom
Gambar 3: Memotong gambar dengan bentuk jalur kustom

Menambahkan batas ke composable Image

Operasi yang umum adalah dengan menggabungkan Modifier.border() dengan Modifier.clip() untuk membuat batas di sekitar gambar:

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

Memotong gambar dan memberikan batas di sekelilingnya
Gambar 4: Memotong gambar dan memberikan batas di sekelilingnya

Jika ingin membuat batas gradien, Anda dapat menggunakan Brush API untuk menggambar batas gradien pelangi di sekitar gambar:

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

Batas lingkaran gradien pelangi
Gambar 5: Batas lingkaran gradien pelangi

Menetapkan rasio aspek kustom

Untuk mengubah gambar menjadi rasio aspek kustom, gunakan Modifier.aspectRatio(16f/9f) untuk memberikan rasio kustom bagi gambar (atau composable apa pun dalam hal ini).

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

Menggunakan Modifier.aspectRatio(16f/9f) pada Image
Gambar 6: Menggunakan Modifier.aspectRatio(16f/9f) pada Gambar

Filter warna - Mengubah warna piksel gambar

Composable Gambar memiliki parameter colorFilter yang dapat mengubah output setiap piksel gambar Anda.

Menambahkan tint pada gambar

Penggunaan ColorFilter.tint(color, blendMode) akan menerapkan mode gabungan dengan warna tertentu ke composable Image Anda. ColorFilter.tint(color, blendMode) menggunakan BlendMode.SrcIn untuk menambahkan tint konten, yang berarti warna yang diberikan akan ditampilkan, dan gambar ditampilkan di layar. Hal ini berguna untuk ikon dan vektor yang perlu diberi tema secara berbeda.

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

ColorFilter.tint diterapkan dengan BlendMode.SrcIn
Gambar 7: ColorFilter.tint diterapkan dengan BlendMode.SrcIn

Hasil BlendMode lain memberikan efek yang berbeda. Misalnya, menyetel BlendMode.Darken dengan Color.Green pada gambar akan memberikan hasil berikut:

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

Tint Color.Green dengan BlendMode.Darken
Gambar 8: Tint Color.Green dengan BlendMode.Darken

Lihat dokumentasi referensi BlendMode untuk informasi selengkapnya tentang berbagai mode campuran yang tersedia.

Menerapkan filter Image dengan matriks warna

Ubah gambar Anda menggunakan opsi ColorFilter matriks warna. Misalnya, untuk menerapkan filter hitam dan putih ke gambar, Anda dapat menggunakan ColorMatrix dan menyetel saturasi ke 0f.

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

Matriks Warna dengan saturasi 0 (gambar hitam putih)
Gambar 9: Matriks Warna dengan saturasi 0 (gambar hitam putih)

Menyesuaikan kontras atau kecerahan composable Image

Untuk mengubah kontras dan kecerahan gambar, Anda dapat menggunakan ColorMatrix untuk mengubah nilainya:

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

Kecerahan dan kontras gambar yang disesuaikan menggunakan ColorMatrix
Gambar 10: Kecerahan dan kontras gambar yang disesuaikan menggunakan ColorMatrix

Melakukan inversi warna composable Image

Untuk melakukan inversi warna gambar, setel ColorMatrix untuk membalik warna:

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

Inversi warna gambar
Gambar 11: Inversi warna gambar

Memberikan efek blur pada composable Image

Untuk memberikan efek blur pada gambar, gunakan Modifier.blur(), yang menyediakan radiusX dan radiusY, yang menentukan radius blur dalam arah horizontal dan vertikal.

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

BlurEffect diterapkan ke gambar
Gambar 12: BlurEffect diterapkan ke gambar

Saat memberikan efek blur pada Images, sebaiknya gunakan BlurredEdgeTreatment(Shape). Jangan gunakan BlurredEdgeTreatment.Unbounded karena digunakan untuk memberikan efek blur pada rendering arbitrer yang diharapkan dirender di luar batas konten asli. Untuk gambar, kemungkinan gambar tidak akan dirender di luar batas konten; sementara memberikan efek blur pada persegi panjang bulat mungkin membutuhkan perbedaan ini.

Misalnya, jika kita menyetel BlurredEdgeTreatment ke Unbounded (Tidak berbatas) pada gambar di atas, tepi gambar akan tampak blur, bukan tajam:

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