Pemburaman di Compose

Efek blur melembutkan detail visual, menciptakan depth of field fotografi, dan menarik fokus ke elemen UI latar depan. Di Jetpack Compose, gunakan Modifier.blur untuk memburamkan konten yang digambar di dalam composable, termasuk gambar, bentuk, teks, dan penampung tata letak. Menerapkan Modifier.blur akan merender composable ke dalam lapisan grafis terpisah.

Kiri: gambar asli. Tengah: gambar dengan blur seragam yang diterapkan di seluruh permukaan. Kanan: gambar dengan blur progresif yang tajam di bagian atas dan meningkat ke arah bawah.
Gambar 1. Kiri: gambar asli. Tengah: gambar dengan blur seragam yang diterapkan di seluruh permukaan. Kanan: gambar dengan blur progresif yang tajam di bagian atas dan meningkat ke arah bawah.

Bergantung pada sasaran desain, Anda dapat memvariasikan blur dengan dua cara:

  • Blur seragam: Menerapkan radius blur yang konstan di seluruh composable, baik secara merata pada kedua sumbu maupun dengan radius horizontal dan vertikal independen (radiusX, radiusY).
  • Blur progresif: Memvariasikan radius blur secara spasial di seluruh composable menggunakan gradien BlurRadiusSpec atau Shader kustom.

Menerapkan blur seragam

Untuk menerapkan blur konstan di seluruh composable, teruskan radius Dp ke Modifier.blur. Teruskan satu nilai radius untuk memburamkan konten secara merata di sepanjang sumbu horizontal (X) dan vertikal (Y):

@Composable
fun UniformBlurExample() {
    Image(
        painter = painterResource(id = R.drawable.dog),
        contentDescription = stringResource(id = R.string.dog_content_description),
        contentScale = ContentScale.Crop,
        modifier = Modifier
            .size(150.dp)
            .blur(
                radius = 8.dp,
                edgeTreatment = BlurredEdgeTreatment(RoundedCornerShape(8.dp)),
            ),
    )
}

Anjing yang diburamkan secara seragam pada sumbu horizontal dan vertikal.
Gambar 2. Anjing yang diburamkan secara seragam pada sumbu horizontal dan vertikal.

Untuk membuat efek motion blur terarah, teruskan nilai radiusX dan radiusY terpisah ke Modifier.blur. radiusX dan radiusY harus lebih besar dari 0.dp agar efek blur diterapkan, seperti yang ditunjukkan dalam contoh berikut:

@Composable
fun DirectionalBlurExample() {
    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 = 2.dp,
                edgeTreatment = BlurredEdgeTreatment(RoundedCornerShape(8.dp)),
            ),
    )
}

Anjing dengan efek blur gerakan horizontal yang kuat.
Gambar 3. Gambar persegi seekor anjing dengan efek blur gerakan horizontal yang kuat.

Menerapkan blur progresif

Blur progresif memvariasikan radius blur di seluruh composable, sehingga menciptakan transisi yang mulus antara area yang tajam dan buram.

Teruskan BlurRadiusSpec ke Modifier.blur. Misalnya, gunakan BlurRadiusSpec.verticalGradient dengan startRadius = 0.dp dan endRadius = 6.dp untuk menjaga bagian atas gambar tetap tajam sambil memburamkannya secara progresif ke arah bawah, seperti yang ditunjukkan dalam contoh berikut:

@Composable
fun ProgressiveBlurExample() {
    Image(
        painter = painterResource(id = R.drawable.dog),
        contentDescription = stringResource(id = R.string.dog_content_description),
        contentScale = ContentScale.Crop,
        modifier = Modifier
            .size(150.dp)
            .blur(
                // Sharp at the top (0.dp), progressively blurred toward the bottom (6.dp)
                blurRadiusSpec = BlurRadiusSpec.verticalGradient(
                    startRadius = 0.dp,
                    endRadius = 6.dp,
                ),
                edgeTreatment = BlurredEdgeTreatment(RoundedCornerShape(8.dp)),
            ),
    )
}

Anjing yang tajam di bagian atas dan secara bertahap menjadi buram ke arah bawah.
Gambar 4. Gambar anjing yang tajam di bagian atas dan secara bertahap menjadi buram ke arah bawah.

Menentukan gradien blur dengan BlurRadiusSpec

Di BlurRadiusSpec, pengukuran ditetapkan dalam Dp dan otomatis disesuaikan dengan ukuran dan kepadatan tampilan lapisan saat digambar. Blur yang bervariasi secara spasial dibatasi hingga 150 piksel setelah dikonversi, sedangkan BlurRadiusSpec.uniform tidak memiliki batas.

Tabel berikut mencantumkan fungsi factory yang tersedia di BlurRadiusSpec:

BlurRadiusSpec factory Deskripsi
BlurRadiusSpec.verticalGradient Mengubah radius blur secara vertikal dengan mulus dari atas (0f) ke bawah (1f) di seluruh lapisan.
BlurRadiusSpec.horizontalGradient Mengubah radius blur secara halus secara horizontal dari tepi kiri (0f) ke tepi kanan (1f).
BlurRadiusSpec.linearGradient Menerapkan transisi blur terarah di sepanjang garis lurus yang menghubungkan koordinat DpOffset tertentu.
BlurRadiusSpec.radialGradient Menyebarkan blur ke luar dari titik fokus ke batas fallOffRadius.
BlurRadiusSpec.uniform Menerapkan radius blur yang merata di seluruh lapisan.
BlurRadiusSpec.shader Menggunakan saluran alfa Shader kustom untuk mengontrol dan menskalakan maxRadius di setiap piksel.

Menyesuaikan distribusi blur dengan BlurStop

Blur gradien standar melakukan interpolasi secara linear antara 0f dan 1f. Untuk menyesuaikan distribusi blur di seluruh permukaan, seperti memburamkan beberapa tepi atau menjaga bagian tengah tetap tajam, teruskan List<BlurStop> yang berisi 2 hingga 16 entri BlurStop ke verticalGradient, horizontalGradient, linearGradient, atau radialGradient. Tentukan hal berikut untuk setiap entri BlurStop:

  • fraction: Posisi relatif di sepanjang gradien dari 0.0f hingga 1.0f. Perhentian diurutkan secara otomatis berdasarkan pecahan.
  • radius: Radius blur dalam Dp yang diterapkan pada posisi pecahan tersebut.

Misalnya, empat perhentian memburamkan tepi atas dan bawah gambar, sekaligus menjaga bagian tengah tetap tajam, seperti yang ditunjukkan dalam contoh berikut:

@Composable
fun MultiStopBlurExample() {
    Image(
        painter = painterResource(id = R.drawable.dog),
        contentDescription = stringResource(id = R.string.dog_content_description),
        contentScale = ContentScale.Crop,
        modifier = Modifier
            .size(150.dp)
            .blur(
                // Blurred at the top and bottom edges, sharp in the middle (0.3f..0.7f)
                blurRadiusSpec = BlurRadiusSpec.verticalGradient(
                    stops = listOf(
                        BlurStop(fraction = 0.0f, radius = 20.dp),
                        BlurStop(fraction = 0.3f, radius = 0.dp),
                        BlurStop(fraction = 0.7f, radius = 0.dp),
                        BlurStop(fraction = 1.0f, radius = 20.dp),
                    ),
                ),
                edgeTreatment = BlurredEdgeTreatment.Unbounded,
            ),
    )
}

Seekor anjing dengan tepi atas dan bawah yang buram, sementara strip horizontal tengah tetap dalam fokus yang tajam.
Gambar 5. Gambar anjing dengan tepi atas dan bawah yang diburamkan, sementara strip horizontal tengah tetap dalam fokus yang tajam.

Mengonfigurasi properti lapisan dengan BlurScope

Alih-alih meneruskan blurRadiusSpec secara langsung, Anda dapat meneruskan blok konfigurasi ke Modifier.blur { ... }. Blok ini berjalan di dalam BlurScope, yang memberi Anda akses langsung ke kepadatan tata letak dan properti berikut:

  • size: DpSize: Lebar dan tinggi lapisan buram yang diukur dalam Dp, yang menentukan ruang koordinat untuk geometri gradien.
  • blurRadiusSpec: BlurRadiusSpec: Konfigurasi radius blur di seluruh platform. Nilai defaultnya adalah BlurRadiusSpec.uniform(0.dp) (tanpa blur).
  • edgeTreatment: BlurredEdgeTreatment: Strategi yang digunakan untuk mengambil sampel dan memangkas piksel di luar batas konten. Nilai defaultnya adalah BlurredEdgeTreatment.Rectangle.
  • alpha: Float: Opasitas lapisan buram dalam rentang 0f..1f. Setelan defaultnya adalah 1f.

Karena blok BlurScope berjalan selama fase lapisan grafis, setelah pengukuran dan tata letak, Anda dapat menghitung geometri gradien dari size tanpa memicu rekomposisi.

Mengontrol pemangkasan tepi dengan BlurredEdgeTreatment

Karena pemburaman mengambil sampel piksel di sekitarnya dalam radius blur, output yang diburamkan akan melampaui batas konten asli sebesar radius blur. BlurredEdgeTreatment menentukan cara piksel di luar batas asli diambil sampelnya dan apakah hasilnya dipangkas menjadi bentuk.

BlurredEdgeTreatment berfungsi dengan blur seragam dan progresif:

BlurredEdgeTreatment Perilaku Output
BlurredEdgeTreatment.Rectangle (default) Memotong hasil blur ke batas persegi panjang konten orisinal dan mengambil sampel piksel tepi terdekat (TileMode.Clamp). Gambar anjing buram yang dipotong menjadi batas persegi panjang yang tajam.
BlurredEdgeTreatment(shape) Memotong hasil blur ke Shape yang ditentukan (seperti RoundedCornerShape(8.dp)) dan mengambil sampel piksel tepi terdekat (TileMode.Clamp). Menjaga hasil blur tetap tajam di batas bentuk tanpa meluber ke luar batas aslinya. Gambar anjing buram yang dipotong menjadi bentuk sudut membulat dengan tepi tajam.
BlurredEdgeTreatment.Unbounded Tidak memotong hasil blur (TileMode.Decal). Piksel di luar batas konten mengambil sampel warna hitam transparan, sehingga tepi luar gambar tampak buram dan blur di luar batas aslinya. Gambar anjing yang diburamkan dengan tepi yang memudar secara halus di luar batas aslinya.

Untuk melihat cara API ini digabungkan dalam pola UI lengkap, seperti memudarkan tepi konten scroll, menyoroti titik fokus, atau menyamarkan blur dengan shading kustom, lihat Kasus penggunaan blur umum.