Kabur jendela

Di Android 12, API publik tersedia untuk menerapkan efek blur jendela, seperti blur latar belakang dan blur di belakang.

Pemburaman jendela, atau pemburaman lintas jendela, digunakan untuk memburamkan layar di belakang jendela yang diberikan. Ada dua jenis buram jendela, yang dapat digunakan untuk mendapatkan efek visual yang berbeda:

  • Latar belakang buram memungkinkan Anda membuat jendela dengan latar belakang buram, sehingga menciptakan efek kaca buram.

  • Blur di belakang memungkinkan Anda memburamkan seluruh layar di belakang jendela (dialog), sehingga menciptakan efek kedalaman bidang.

Kedua efek dapat digunakan secara terpisah atau digabungkan, seperti yang ditunjukkan pada gambar berikut:

hanya blur latar belakang

a

hanya blur di belakang

b

blur di belakang dan blur latar belakang

c

Gambar 1. Hanya blur latar belakang (a), hanya blur di belakang (b), blur latar belakang dan blur di belakang (c)

Fitur keburaman jendela berfungsi di seluruh jendela, yang berarti fitur ini juga berfungsi saat ada aplikasi lain di belakang jendela Anda. Efek ini tidak sama dengan efek rendering blur, yang memburamkan konten di dalam jendela yang sama. Pemburaman jendela berguna untuk dialog, sheet bawah, dan jendela mengambang lainnya.

Implementasi

Developer aplikasi

Developer aplikasi harus memberikan radius blur untuk membuat efek blur. Radius blur mengontrol seberapa padat blur, yaitu makin tinggi radiusnya, makin padat blur. Blur 0 px berarti tidak ada blur. Untuk blur di belakang, radius 20 px menciptakan efek kedalaman bidang yang baik, sementara radius blur latar belakang 80 px menciptakan efek kaca buram yang baik. Hindari radius blur yang lebih tinggi dari 150 px, karena hal ini akan memengaruhi performa secara signifikan.

Untuk mendapatkan efek buram yang diinginkan dan meningkatkan keterbacaan, pilih nilai radius buram yang dilengkapi dengan lapisan warna transparan.

Blur latar belakang

Gunakan blur latar belakang pada jendela mengambang untuk membuat efek latar belakang jendela yang merupakan gambar buram dari konten yang mendasarinya. Untuk menambahkan latar belakang buram pada jendela Anda, lakukan hal berikut:

  1. Panggil Window#setBackgroundBlurRadius(int) untuk menetapkan radius buram latar belakang. Atau, di tema jendela, tetapkan R.attr.windowBackgroundBlurRadius.

  2. Tetapkan R.attr.windowIsTranslucent ke benar (true) untuk membuat jendela transparan. Blur digambar di bawah permukaan jendela, sehingga jendela harus transparan agar blur dapat terlihat.

  3. Secara opsional, panggil Window#setBackgroundDrawableResource(int) untuk menambahkan drawable latar belakang jendela persegi panjang dengan warna transparan. Atau, di tema jendela, tetapkan R.attr.windowBackground.

  4. Untuk jendela dengan sudut melengkung, tentukan sudut melengkung untuk area yang diblur dengan menyetel ShapeDrawable dengan sudut melengkung sebagai drawable latar belakang jendela.

  5. Menangani status aktif dan nonaktif blur. Lihat bagian Panduan untuk menggunakan blur jendela di aplikasi untuk mengetahui informasi selengkapnya.

Blur di belakang

Latar belakang buram akan memburamkan seluruh layar di belakang jendela. Efek ini digunakan untuk mengarahkan perhatian pengguna ke konten jendela dengan mengaburkan apa pun di layar di belakang jendela.

Untuk mengaburkan konten di belakang jendela Anda, ikuti langkah-langkah berikut:

  1. Tambahkan FLAG_BLUR_BEHIND ke tanda jendela, untuk mengaktifkan buram di belakang. Atau, di tema jendela, tetapkan R.attr.windowBlurBehindEnabled.

  2. Panggil WindowManager.LayoutParams#setBlurBehindRadius untuk menetapkan radius di belakang blur. Atau, di tema jendela, tetapkan R.attr.windowBlurBehindRadius.

  3. Jika mau, pilih jumlah peredupan yang melengkapi.

  4. Menangani status aktif dan nonaktif blur. Lihat bagian Panduan untuk menggunakan blur jendela di aplikasi untuk mengetahui informasi selengkapnya.

Panduan penggunaan buram jendela di aplikasi

Dukungan untuk buram jendela bergantung pada hal berikut:

  • Versi Android: API blur jendela hanya tersedia di Android 12 dan yang lebih tinggi. Periksa SDK perangkat untuk versi Android.

  • Performa grafis: Perangkat dengan GPU yang performanya lebih rendah mungkin memilih untuk tidak mendukung buram jendela.

  • Status sistem: Server sistem mungkin menonaktifkan sementara efek buram jendela saat runtime, misalnya, selama mode hemat baterai, saat memutar jenis konten video tertentu, atau karena penggantian developer.

Untuk membuat aplikasi Anda kompatibel di seluruh versi Android, perangkat, dan status sistem, ikuti panduan berikut:

  • Tambahkan pemroses melalui WindowManager#addCrossWindowBlurEnabledListener, untuk memberi tahu Anda saat buram jendela diaktifkan atau dinonaktifkan. Selain itu, gunakan WindowManager#isCrossWindowBlurEnabled untuk membuat kueri apakah buram jendela saat ini diaktifkan.

  • Terapkan dua versi untuk latar belakang jendela, untuk mengakomodasi status aktif atau nonaktif dari efek blur jendela.

    Jika efek buram diaktifkan, latar belakang jendela harus transparan agar efek buram terlihat. Dalam status ini, saat keburaman dinonaktifkan, konten jendela tumpang-tindih secara langsung dengan konten jendela di bawahnya, sehingga jendela yang tumpang-tindih menjadi kurang terbaca. Untuk menghindari efek tersebut, saat blur jendela dinonaktifkan, sesuaikan UI aplikasi sebagai berikut:

    • Untuk blur latar belakang, tingkatkan alfa drawable latar belakang jendela, sehingga lebih buram.

    • Untuk blur di belakang, tambahkan lapisan redup dengan jumlah peredupan yang lebih tinggi.

Contoh pemburaman di belakang dan pemburaman latar belakang

Bagian ini memberikan contoh praktis aktivitas yang menggunakan blur di belakang dan blur latar belakang.

Contoh MainActivity.java berikut adalah dialog dengan radius di belakang blur 20 px dan radius blur latar belakang 80 px. Memiliki sudut melengkung, yang ditentukan dalam xml di drawable latar belakang jendela. Aplikasi ini menangani berbagai versi Android, berbagai perangkat (yang berpotensi tidak mendukung buram jendela) dan perubahan buram yang diaktifkan atau dinonaktifkan saat runtime dengan benar. Hal ini memastikan bahwa konten dialog dapat dibaca dalam kondisi apa pun dengan menyesuaikan alfa drawable latar belakang jendela dan jumlah peredupan jendela.

public class MainActivity extends Activity {

    private final int mBackgroundBlurRadius = 80;
    private final int mBlurBehindRadius = 20;

    // We set a different dim amount depending on whether window blur is enabled or disabled
    private final float mDimAmountWithBlur = 0.1f;
    private final float mDimAmountNoBlur = 0.4f;

    // We set a different alpha depending on whether window blur is enabled or disabled
    private final int mWindowBackgroundAlphaWithBlur = 170;
    private final int mWindowBackgroundAlphaNoBlur = 255;

    // Use a rectangular shape drawable for the window background. The outline of this drawable
    // dictates the shape and rounded corners for the window background blur area.
    private Drawable mWindowBackgroundDrawable;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mWindowBackgroundDrawable = getDrawable(R.drawable.window_background);
        getWindow().setBackgroundDrawable(mWindowBackgroundDrawable);

        if (buildIsAtLeastS()) {
            // Enable blur behind. This can also be done in xml with R.attr#windowBlurBehindEnabled
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND);

            // Register a listener to adjust window UI whenever window blurs are enabled/disabled
            setupWindowBlurListener();
        } else {
            // Window blurs are not available prior to Android S
            updateWindowForBlurs(false /* blursEnabled */);
        }

        // Enable dim. This can also be done in xml, see R.attr#backgroundDimEnabled
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
    }

    /**
     * Set up a window blur listener.
     *
     * Window blurs might be disabled at runtime in response to user preferences or system states
     * (e.g. battery saving mode). WindowManager#addCrossWindowBlurEnabledListener allows to
     * listen for when that happens. In that callback we adjust the UI to account for the
     * added/missing window blurs.
     *
     * For the window background blur we adjust the window background drawable alpha:
     *     - lower when window blurs are enabled to make the blur visible through the window
     *       background drawable
     *     - higher when window blurs are disabled to ensure that the window contents are readable
     *
     * For window blur behind we adjust the dim amount:
     *     - higher when window blurs are disabled - the dim creates a depth of field effect,
     *       bringing the user's attention to the dialog window
     *     - lower when window blurs are enabled - no need for a high alpha, the blur behind is
     *       enough to create a depth of field effect
     */
    @RequiresApi(api = Build.VERSION_CODES.S)
    private void setupWindowBlurListener() {
        Consumer<Boolean> windowBlurEnabledListener = this::updateWindowForBlurs;
        getWindow().getDecorView().addOnAttachStateChangeListener(
                new View.OnAttachStateChangeListener() {
                    @Override
                    public void onViewAttachedToWindow(View v) {
                        getWindowManager().addCrossWindowBlurEnabledListener(
                                windowBlurEnabledListener);
                    }

                    @Override
                    public void onViewDetachedFromWindow(View v) {
                        getWindowManager().removeCrossWindowBlurEnabledListener(
                                windowBlurEnabledListener);
                    }
                });
    }

    private void updateWindowForBlurs(boolean blursEnabled) {
        mWindowBackgroundDrawable.setAlpha(blursEnabled && mBackgroundBlurRadius > 0 ?
                mWindowBackgroundAlphaWithBlur : mWindowBackgroundAlphaNoBlur);
        getWindow().setDimAmount(blursEnabled && mBlurBehindRadius > 0 ?
                mDimAmountWithBlur : mDimAmountNoBlur);

        if (buildIsAtLeastS()) {
            // Set the window background blur and blur behind radii
            getWindow().setBackgroundBlurRadius(mBackgroundBlurRadius);
            getWindow().getAttributes().setBlurBehindRadius(mBlurBehindRadius);
            getWindow().setAttributes(getWindow().getAttributes());
        }
    }

    private static boolean buildIsAtLeastS() {
        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.S;
    }
}

Untuk membuat sudut bulat pada jendela, kita menentukan latar belakang jendela di res/drawable/window_background.xml sebagai ShapeDrawable dengan sudut bulat dengan radius 20 dp sebagai berikut:

<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
    <corners android:radius="20dp"/>
    <solid android:color="#AAAAAA"/>
</shape>

Efek buram jendela memburamkan konten jendela di bawah aktivitas. Gambar yang diburamkan digambar di bawah jendela aktivitas ini, sehingga jendela aktivitas harus transparan agar pemburaman dapat terlihat. Untuk membuat jendela transparan, kita menetapkan R.attr.windowIsTranslucent di tema aktivitas sebagai berikut:

<style name="Theme.BlurryDialog" parent="Theme.MaterialComponents.Dialog">
    <item name="android:windowIsTranslucent">true</item>
</style>

OEM dan partner

Agar perangkat dapat menerapkan pemburaman jendela, OEM harus menyatakan bahwa perangkat tersebut mendukung pemburaman jendela.

Untuk memeriksa apakah perangkat Anda dapat mendukung buram jendela, lakukan hal berikut:

  • Pastikan perangkat dapat menangani beban GPU tambahan. Perangkat kelas bawah mungkin tidak dapat menangani beban tambahan, yang dapat menyebabkan frame terputus. Hanya aktifkan buram jendela pada perangkat yang telah diuji dengan daya GPU yang memadai.

  • Jika Anda memiliki mesin render yang disesuaikan, pastikan mesin render Anda menerapkan logika blur. Mesin rendering Android 12 default menerapkan logika pengaburan di BlurFilter.cpp.

Setelah memastikan bahwa perangkat Anda dapat mendukung buram jendela, tetapkan sysprop surface flinger berikut:

PRODUCT_VENDOR_PROPERTIES += \
       ro.surface_flinger.supports_background_blur=1

Validasi

Untuk memvalidasi bahwa jendela aplikasi Anda ditangani dengan benar saat beralih antara status blur diaktifkan dan blur dinonaktifkan, ikuti langkah-langkah berikut:

  1. Buka UI yang memiliki blur.

  2. Aktifkan atau nonaktifkan buram jendela dengan mengaktifkan dan menonaktifkan buram jendela.

  3. Verifikasi bahwa UI jendela berubah ke dan dari status buram seperti yang diharapkan.

Mengaktifkan dan menonaktifkan blur jendela

Untuk menguji cara UI jendela dirender dengan efek buram jendela, aktifkan atau nonaktifkan efek buram menggunakan salah satu metode berikut:

  • Dari Opsi Developer:

    Setelan -> Sistem -> Opsi developer -> Rendering yang dipercepat hardware -> Izinkan blur tingkat jendela

  • Dari terminal di perangkat yang di-root:

    adb shell wm disable-blur 1 # 1 disables window blurs, 0 allows them

Untuk memeriksa apakah perangkat Android 12+ Anda mendukung buram jendela dan apakah buram jendela saat ini diaktifkan, jalankan adb shell wm disable-blur di perangkat yang di-root.

Pemecahan masalah

Gunakan hal berikut sebagai panduan untuk memecahkan masalah selama validasi.

Tidak ada keburaman yang digambar

  • Pastikan buram saat ini diaktifkan dan hardware Anda mendukungnya. Lihat Mengaktifkan dan menonaktifkan efek buram jendela.

  • Pastikan Anda menyetel warna latar belakang jendela transparan. Warna latar belakang jendela buram menyembunyikan area yang diburamkan.

Perangkat pengujian tidak mendukung buram jendela

  • Uji aplikasi Anda di emulator Android 12. Untuk menyiapkan emulator Android, lihat Menyiapkan emulator Android. Perangkat virtual Android yang Anda buat dengan emulator mendukung buram jendela.

Tanpa sudut melengkung

Memperbarui opsi developer tidak akan mengaktifkan efek blur

  • Periksa apakah perangkat berada dalam mode hemat baterai atau apakah perangkat menggunakan tunneling multimedia. Di beberapa perangkat TV, buram jendela juga dapat dinonaktifkan selama pemutaran video.

Blur latar belakang digambar dalam layar penuh, bukan dalam batas jendela

Pembaruan dari pemroses tidak diterapkan di layar

  • Pembaruan pemroses mungkin diterapkan ke instance jendela lama. Periksa apakah jendela dihancurkan dan dibuat ulang dengan pembaruan pendengar yang tepat.