نافذة ضبابية

في Android 12، تتوفر واجهات برمجة التطبيقات العامة لتنفيذ تأثيرات تمويه النافذة، مثل تمويه الخلفية والتعتيم في الخلف.

يتم استخدام تمويه النوافذ أو تمويه النوافذ المتقاطعة لتشويش الشاشة خلف النافذة المحددة. هناك نوعان من تمويه النوافذ، يمكن استخدامهما لتحقيق تأثيرات بصرية مختلفة:

  • يتيح لك تمويه الخلفية إنشاء نوافذ بخلفيات غير واضحة، مما يؤدي إلى إنشاء تأثير زجاج بلوري.

  • يتيح لك Blur Behind طمس الشاشة بأكملها خلف نافذة (الحوار)، مما يؤدي إلى إنشاء تأثير عميق للمجال.

ويمكن استخدام التأثيرين بشكل منفصل أو مجتمعين، كما هو موضح في الشكل التالي:

طمس الخلفية فقط

أ

طمس وراء فقط

ب

طمس وراء وطمس الخلفية

ج

الشكل 1. طمس الخلفية فقط (أ)، طمس خلف فقط (ب)، طمس الخلفية وطمس خلف (ج)

تعمل ميزة تمويه النافذة عبر النوافذ، مما يعني أنها تعمل أيضًا عندما يكون هناك تطبيق آخر خلف نافذتك. هذا التأثير ليس هو نفسه تأثير التمويه ، الذي يؤدي إلى تشويش المحتوى الموجود داخل نفس النافذة. تعتبر تمويه النوافذ مفيدة لمربعات الحوار والأوراق السفلية والنوافذ العائمة الأخرى.

تطبيق

مطوري التطبيقات

يجب على مطوري التطبيقات توفير نصف قطر تمويه لإنشاء تأثير تمويه. يتحكم نصف قطر التمويه في مدى كثافة التمويه، أي أنه كلما زاد نصف القطر، زادت كثافة التمويه. التمويه بمقدار 0 بكسل يعني عدم وجود ضبابية. بالنسبة للضبابية الخلفية، فإن نصف قطر 20 بيكسل يخلق عمقًا جيدًا لتأثير المجال، في حين أن نصف قطر تمويه الخلفية 80 بيكسل يخلق تأثيرًا زجاجيًا بلوريًا جيدًا. تجنب أن يكون نصف قطر التمويه أعلى من 150 بكسل، حيث سيؤثر ذلك بشكل كبير على الأداء.

لتحقيق تأثير التمويه المطلوب وزيادة إمكانية القراءة، اختر قيمة نصف قطر التمويه مكملة بطبقة شفافة من الألوان.

طمس الخلفية

استخدم تمويه الخلفية على النوافذ العائمة لإنشاء تأثير خلفية النافذة وهو عبارة عن صورة غير واضحة للمحتوى الأساسي. لإضافة خلفية غير واضحة لنافذتك، قم بما يلي:

  1. استدعاء Window#setBackgroundBlurRadius(int) لتعيين نصف قطر تمويه الخلفية. أو، في سمة النافذة، قم بتعيين R.attr.windowBackgroundBlurRadius .

  2. اضبط R.attr.windowIsTranslucent على true لجعل النافذة شفافة. يتم رسم التمويه أسفل سطح النافذة، لذلك يجب أن تكون النافذة شفافة حتى يكون التمويه مرئيًا.

  3. اختياريًا، قم باستدعاء Window#setBackgroundDrawableResource(int) لإضافة خلفية نافذة مستطيلة قابلة للرسم بلون شفاف. أو، في سمة النافذة، قم بتعيين R.attr.windowBackground .

  4. بالنسبة لنافذة ذات زوايا مستديرة، حدد الزوايا الدائرية للمنطقة المموهة عن طريق تعيين ShapeDrawable بزوايا مستديرة كخلفية نافذة قابلة للرسم.

  5. التعامل مع حالات التمكين والمعاقين. راجع إرشادات استخدام تمويه النافذة في قسم التطبيقات لمزيد من المعلومات.

طمس وراء

يؤدي التمويه الموجود في الخلف إلى تشويش الشاشة بأكملها خلف النافذة. يُستخدم هذا التأثير لتوجيه انتباه المستخدم نحو محتوى النافذة عن طريق طمس أي شيء على الشاشة خلف النافذة.

لتعتيم المحتوى الموجود خلف نافذتك، اتبع الخطوات التالية:

  1. أضف FLAG_BLUR_BEHIND إلى علامات النافذة لتمكين التمويه في الخلف. أو، في سمة النافذة، قم بتعيين R.attr.windowBlurBehindEnabled .

  2. اتصل بـ WindowManager.LayoutParams#setBlurBehindRadius لتعيين التمويه خلف نصف القطر. أو، في سمة النافذة، قم بتعيين R.attr.windowBlurBehindRadius .

  3. اختياريًا، اختر كمية خافتة مكملة.

  4. التعامل مع حالات التمكين والمعاقين. راجع إرشادات استخدام تمويه النافذة في قسم التطبيقات لمزيد من المعلومات.

إرشادات لاستخدام تمويه النوافذ في التطبيقات

يعتمد دعم Windows Blur على ما يلي:

  • إصدار Android: تتوفر واجهات برمجة تطبيقات Windows Blur فقط على نظام التشغيل Android 12 والإصدارات الأحدث. تحقق من SDK للجهاز لمعرفة إصدار Android.

  • أداء الرسومات: قد تختار الأجهزة ذات وحدات معالجة الرسومات الأقل أداءً عدم دعم تمويه النوافذ.

  • حالة النظام: قد يقوم خادم النظام بتعطيل تمويه النوافذ مؤقتًا في وقت التشغيل، على سبيل المثال، أثناء وضع توفير طاقة البطارية، أثناء تشغيل أنواع معينة من محتوى الفيديو أو بسبب تجاوز المطور.

لجعل تطبيقك متوافقًا عبر إصدارات Android والأجهزة وحالات النظام، اتبع الإرشادات التالية:

  • قم بإضافة مستمع من خلال WindowManager#addCrossWindowBlurEnabledListener لإعلامك عند تمكين أو تعطيل تمويه النافذة. بالإضافة إلى ذلك، استخدم WindowManager#isCrossWindowBlurEnabled للاستعلام عما إذا كانت تمويه النوافذ ممكّنة حاليًا.

  • قم بتنفيذ نسختين لخلفية النافذة، لاستيعاب حالة تمويه النافذة الممكّنة أو المعطلة.

    عند تمكين التمويه، يجب أن تكون خلفية النافذة شفافة لجعل التمويه مرئيًا. في هذه الحالة، عندما يتم تعطيل التمويه، يتداخل محتوى النافذة مباشرة مع محتوى النافذة الأساسية، مما يجعل النافذة المتداخلة أقل وضوحًا. لتجنب مثل هذا التأثير، عند تعطيل تمويه النوافذ، قم بتعديل واجهة مستخدم التطبيق على النحو التالي:

    • لتعتيم الخلفية، قم بزيادة مستوى ألفا لخلفية النافذة القابلة للرسم، مما يجعلها أكثر عتامة.

    • للتمويه في الخلف، قم بإضافة طبقة قاتمة بكمية خافتة أعلى.

مثال على التمويه في الخلف وطمس الخلفية

يقدم هذا القسم مثالاً عمليًا لنشاط يستخدم كلاً من التمويه الخلفي وتمويه الخلفية.

المثال التالي لـ MainActivity.java عبارة عن مربع حوار به تمويه خلف نصف قطر يبلغ 20 بكسل ونصف قطر تمويه في الخلفية يبلغ 80 بكسل. يحتوي على زوايا مستديرة، محددة بتنسيق XML في خلفية النافذة القابلة للرسم. إنه يتعامل بشكل صحيح مع إصدارات Android المختلفة، والأجهزة المختلفة (التي من المحتمل ألا تدعم تمويه النوافذ) والتغييرات التي تم تمكينها أو تعطيلها في وقت التشغيل. إنه يضمن أن محتوى الحوار قابل للقراءة في ظل أي من هذه الظروف عن طريق ضبط ألفا الخلفية القابلة للرسم ومقدار تعتيم النافذة.

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;
    }
}

لإنشاء زوايا مستديرة للنافذة، نحدد خلفية النافذة في res/drawable/window_background.xml على أنها ShapeDrawable بزوايا مستديرة بنصف قطر 20 dp كما يلي:

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

تمويه النافذة يؤدي إلى تشويش محتوى النافذة الموجودة أسفل النشاط. يتم رسم الصورة المموهة أسفل نافذة النشاط هذه، لذا يجب أن تكون نافذة النشاط شفافة للسماح بظهور التمويه. لجعل النافذة شفافة قمنا بتعيين R.attr.windowIsTranslucent في سمة النشاط على النحو التالي:

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

مصنعي المعدات الأصلية والشركاء

لتعتيم النوافذ على الجهاز، يجب على الشركة المصنّعة للمعدات الأصلية (OEM) الإعلان عن أن الجهاز يدعم تعتيم النوافذ.

للتحقق مما إذا كان جهازك يمكنه دعم تمويه النوافذ، قم بما يلي:

  • تأكد من أن الجهاز يمكنه التعامل مع حمل GPU الإضافي. قد لا تتمكن الأجهزة ذات المواصفات المنخفضة من التعامل مع الحمل الإضافي، مما قد يؤدي إلى إسقاط الإطارات. قم بتمكين تمويه النوافذ فقط على الأجهزة التي تم اختبارها والتي تتمتع بطاقة GPU كافية.

  • إذا كان لديك محرك تجسيد مخصص، فتأكد من أن محرك التجسيد الخاص بك ينفذ منطق التمويه. ينفذ محرك العرض الافتراضي في Android 12 منطق التمويه في BlurFilter.cpp .

بمجرد التأكد من أن جهازك يمكنه دعم تمويه النوافذ، قم بتعيين sysprop للسطح التالي:

PRODUCT_VENDOR_PROPERTIES += \
       ro.surface_flinger.supports_background_blur=1

تصديق

للتحقق من أن نافذة تطبيقك تتمتع بالمعالجة المناسبة عند التبديل بين حالة تمكين التمويه وحالة تعطيل التمويه، اتبع الخطوات التالية:

  1. افتح واجهة المستخدم التي تحتوي على تمويه.

  2. قم بتمكين تمويه النافذة أو تعطيله عن طريق تشغيل تمويه النافذة وإيقاف تشغيله .

  3. تحقق من أن واجهة مستخدم النافذة تتغير من وإلى حالة عدم الوضوح كما هو متوقع.

تشغيل وإيقاف تعتيم النافذة

لاختبار كيفية عرض واجهة مستخدم النافذة مع تأثير تمويه النافذة، قم بتمكين التمويه أو تعطيله باستخدام إحدى الطرق التالية:

  • من خيارات المطور:

    الإعدادات -> النظام -> خيارات المطور -> العرض المسرع بالأجهزة -> السماح بالتعتيم على مستوى النافذة

  • من المحطة على جهاز جذر:

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

للتحقق مما إذا كان جهازك الذي يعمل بنظام التشغيل Android 12+ يدعم تمويه النوافذ وما إذا كانت تمويه النوافذ ممكّنة حاليًا، قم بتشغيل adb shell wm disable-blur على جهاز جذر.

استكشاف الأخطاء وإصلاحها

استخدم ما يلي كدليل لاستكشاف الأخطاء وإصلاحها أثناء التحقق من الصحة.

لا طمس مرسومة

  • تحقق من تمكين التمويه حاليًا وأن أجهزتك تدعمها. ارجع إلى تشغيل وإيقاف تمويه النافذة .

  • تأكد من ضبط لون خلفية النافذة الشفافة. يخفي لون خلفية النافذة المعتمة المنطقة غير الواضحة.

جهاز الاختبار لا يدعم تمويه النوافذ

  • اختبر تطبيقك على محاكي Android 12. لإعداد محاكي Android، راجع إعداد محاكي Android . أي جهاز افتراضي يعمل بنظام Android تقوم بإنشائه باستخدام المحاكي يدعم تمويه النوافذ.

لا زوايا مستديرة

لا يؤدي تحديث خيار المطور إلى تمكين التمويه

  • تحقق مما إذا كان الجهاز في وضع توفير البطارية أو ما إذا كان يستخدم نفق الوسائط المتعددة . قد يتم أيضًا تعطيل تمويه النوافذ في بعض أجهزة التلفزيون أثناء تشغيل الفيديو.

تم رسم خلفية ضبابية بملء الشاشة، وليس ضمن حدود النافذة

لا يتم تطبيق التحديثات من المستمع على الشاشة

  • قد يتم تطبيق تحديثات المستمع على مثيل نافذة قديم. تحقق مما إذا تم تدمير النافذة وإعادة إنشائها باستخدام تحديث المستمع المناسب.