Jendela kabur

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

Keburaman jendela, atau keburaman lintas jendela, digunakan untuk mengaburkan layar di belakang jendela tertentu. Ada dua jenis keburaman jendela, yang dapat digunakan untuk mendapatkan efek visual yang berbeda:

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

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

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

latar belakang buram saja

A

kabur di belakang saja

B

kabur di belakang dan latar belakang kabur

C

Gambar 1. Background blur saja (a), blur di belakang saja (b), background blur dan blur di belakang (c)

Fitur buram 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 blur render , yang mengaburkan konten di dalam jendela yang sama. Keburaman jendela berguna untuk dialog, lembar bawah, dan jendela mengambang lainnya.

Penerapan

Pengembang aplikasi

Pengembang aplikasi harus menyediakan radius blur untuk menciptakan efek blur. Jari-jari keburaman mengontrol seberapa pekat keburamannya, yaitu semakin tinggi radiusnya, semakin pekat keburamannya. Blur sebesar 0 px berarti tidak ada blur. Untuk keburaman di belakang, radius 20 px menciptakan efek kedalaman bidang yang bagus, sedangkan radius keburaman latar belakang 80 px menciptakan efek kaca buram yang bagus. Hindari radius keburaman lebih tinggi dari 150 piksel, karena ini akan berdampak signifikan pada kinerja.

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

Latar belakang kabur

Gunakan keburaman latar belakang pada jendela mengambang untuk menciptakan 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 menyetel radius keburaman latar belakang. Atau, di tema jendela, atur R.attr.windowBackgroundBlurRadius .

  2. Atur R.attr.windowIsTranslucent ke true untuk membuat jendela tembus cahaya. Keburaman digambar di bawah permukaan jendela, jadi jendela harus tembus cahaya agar keburaman terlihat.

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

  4. Untuk jendela dengan sudut membulat, tentukan sudut membulat untuk area yang diburamkan dengan mengatur ShapeDrawable dengan sudut membulat sebagai gambar latar belakang jendela.

  5. Menangani status blur yang diaktifkan dan dinonaktifkan. Lihat bagian Pedoman untuk menggunakan keburaman jendela di aplikasi untuk informasi lebih lanjut.

Buram di belakang

Keburaman di belakang mengaburkan seluruh layar di belakang jendela. Efek ini digunakan untuk mengarahkan perhatian pengguna terhadap konten jendela dengan memburamkan apa pun pada layar di belakang jendela.

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

  1. Tambahkan FLAG_BLUR_BEHIND ke bendera jendela, untuk mengaktifkan keburaman di belakang. Atau, di tema jendela, atur R.attr.windowBlurBehindEnabled .

  2. Panggil WindowManager.LayoutParams#setBlurBehindRadius untuk menyetel keburaman di belakang radius. Atau, di tema jendela, atur R.attr.windowBlurBehindRadius .

  3. Secara opsional, pilih jumlah redup yang melengkapi.

  4. Menangani status blur yang diaktifkan dan dinonaktifkan. Lihat bagian Pedoman untuk menggunakan keburaman jendela di aplikasi untuk informasi lebih lanjut.

Pedoman untuk menggunakan keburaman jendela di aplikasi

Dukungan untuk windows blur bergantung pada hal berikut:

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

  • Performa grafis: Perangkat dengan GPU berperforma lebih rendah mungkin memilih untuk tidak mendukung keburaman jendela.

  • Status sistem: Server sistem mungkin menonaktifkan sementara kekaburan jendela saat runtime, misalnya, selama mode hemat baterai, saat memutar jenis konten video tertentu, atau karena kelalaian pengembang.

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

  • Tambahkan pendengar melalui WindowManager#addCrossWindowBlurEnabledListener , untuk memberi tahu Anda saat keburaman jendela diaktifkan atau dinonaktifkan. Selain itu, gunakan WindowManager#isCrossWindowBlurEnabled untuk menanyakan apakah keburaman jendela saat ini diaktifkan.

  • Terapkan dua versi untuk latar belakang jendela, untuk mengakomodasi keadaan keburaman jendela yang diaktifkan atau dinonaktifkan.

    Saat keburaman diaktifkan, latar belakang jendela harus tembus cahaya agar keburaman terlihat. Dalam keadaan ini, ketika keburaman dinonaktifkan, konten jendela secara langsung tumpang tindih dengan konten jendela yang mendasarinya, sehingga membuat jendela yang tumpang tindih menjadi kurang terbaca. Untuk menghindari efek seperti itu, ketika keburaman jendela dinonaktifkan, sesuaikan UI aplikasi sebagai berikut:

    • Untuk keburaman latar belakang, tingkatkan alfa gambar latar belakang jendela, sehingga membuatnya lebih buram.

    • Untuk keburaman di belakang, tambahkan layer redup dengan jumlah redup yang lebih tinggi.

Contoh blur dibelakang dan background blur

Bagian ini memberikan contoh kerja aktivitas yang menggunakan keburaman di belakang dan keburaman latar belakang.

Contoh MainActivity.java berikut adalah dialog dengan radius blur di belakang 20 px dan radius blur latar belakang 80 px. Ini memiliki sudut membulat, ditentukan dalam xml di latar belakang jendela yang dapat digambar. Ini dengan benar menangani versi Android yang berbeda, perangkat yang berbeda (yang mungkin tidak mendukung kekaburan jendela) dan perubahan yang diaktifkan atau dinonaktifkan keburaman waktu proses. Hal ini memastikan bahwa konten dialog dapat dibaca dalam kondisi mana 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 membulat pada jendela, kita mendefinisikan latar belakang jendela di res/drawable/window_background.xml sebagai ShapeDrawable dengan sudut membulat 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>

Keburaman jendela mengaburkan konten jendela di bawah aktivitas. Gambar buram digambar di bawah jendela aktivitas ini, sehingga jendela aktivitas harus tembus cahaya agar keburaman dapat terlihat. Untuk membuat jendela tembus pandang, kami menetapkan R.attr.windowIsTranslucent dalam tema aktivitas sebagai berikut:

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

OEM dan mitra

Untuk membuat jendela menjadi buram pada perangkat, OEM perlu menyatakan bahwa perangkat tersebut mendukung keburaman jendela.

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

  • Pastikan perangkat dapat menangani beban GPU tambahan. Perangkat kelas bawah mungkin tidak mampu menangani beban ekstra, yang dapat menyebabkan frame terjatuh. Hanya aktifkan keburaman jendela pada perangkat yang diuji dengan daya GPU yang memadai.

  • Jika Anda memiliki mesin render yang disesuaikan, pastikan mesin render Anda mengimplementasikan logika pemburaman. Mesin render Android 12 default mengimplementasikan logika pemburaman di BlurFilter.cpp .

Setelah Anda memastikan bahwa perangkat Anda dapat mendukung keburaman jendela, atur sysprop flinger permukaan berikut :

PRODUCT_VENDOR_PROPERTIES += \
       ro.surface_flinger.supports_background_blur=1

Validasi

Untuk memvalidasi bahwa jendela aplikasi Anda memiliki penanganan yang tepat saat beralih antara status blur diaktifkan dan blur dinonaktifkan, ikuti langkah-langkah berikut:

  1. Buka UI yang blur.

  2. Mengaktifkan atau menonaktifkan keburaman jendela dengan mengaktifkan dan menonaktifkan keburaman jendela .

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

Mengaktifkan dan menonaktifkan keburaman jendela

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

  • Dari Opsi Pengembang:

    Pengaturan -> Sistem -> Opsi pengembang -> Perenderan yang dipercepat perangkat keras -> Izinkan keburaman tingkat jendela

  • Dari terminal pada perangkat yang di-rooting:

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

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

Penyelesaian masalah

Gunakan yang berikut ini sebagai panduan untuk pemecahan masalah selama validasi.

Tidak ada gambar buram

  • Pastikan blur saat ini diaktifkan dan perangkat keras Anda mendukungnya. Lihat Mengaktifkan dan menonaktifkan keburaman jendela .

  • Pastikan Anda mengatur warna latar belakang jendela tembus pandang. Warna latar belakang jendela buram menyembunyikan area buram.

Perangkat uji tidak mendukung keburaman jendela

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

Tidak ada sudut membulat

Memperbarui opsi pengembang tidak mengaktifkan keburaman

  • Periksa apakah perangkat berada dalam mode hemat baterai atau menggunakan terowongan multimedia . Pada beberapa perangkat TV, keburaman jendela mungkin juga dinonaktifkan selama pemutaran video.

Latar belakang buram digambar dalam layar penuh, bukan dalam batas jendela

Pembaruan dari pendengar tidak diterapkan di layar

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