في Android 12، تتوفّر واجهات برمجة التطبيقات العامة لتطبيق تأثيرات التمويه على النوافذ، مثل التمويه في الخلفية والتمويه في الخلف.
يتم استخدام تمويهات النوافذ أو تمويهات النوافذ المتداخلة لتمويه الشاشة خلف النافذة المحدّدة. هناك نوعان من تمويهات النوافذ، ويمكن استخدامهما لتحقيق تأثيرات مرئية مختلفة:
يتيح لك تمويه الخلفية إنشاء نوافذ بخلفيات مموّهة، مما يخلق تأثيرًا زجاجيًا مموهًا.
يتيح لك خيار التمويه في الخلفية تمويه الشاشة بأكملها خلف نافذة (مربّع حوار)، مما يؤدي إلى خلق تأثير عمق المجال.
يمكن استخدام هذين التأثيرَين بشكل منفصل أو معًا، كما هو موضّح في الشكل التالي:
![]() a |
![]() ب |
![]() c |
الشكل 1: تمويه الخلفية فقط (أ)، تمويه الجزء الخلفي فقط (ب)، تمويه الخلفية وتمويه الجزء الخلفي (ج)
تعمل ميزة التمويه في النوافذ على جميع النوافذ، ما يعني أنّها تعمل أيضًا عند توفُّر تطبيق آخر خلف نافذتك. لا يشبه هذا التأثير تأثير التمويه، الذي يؤدي إلى تمويه المحتوى داخل النافذة نفسها. إنّ تمويه النوافذ مفعّل في مربّعات الحوار والبطاقات السفلية وغيرها من النوافذ العائمة.
التنفيذ
مطوّرو التطبيقات
على مطوّري التطبيقات تقديم نصف قطر التمويه لإنشاء تأثير التمويه. يتحكّم نصف قطر التمويه في كثافة التمويه، أي كلما زاد نصف القطر، زادت كثافة التمويه. يعني التمويه الذي يبلغ 0 بكسل عدم التمويه. بالنسبة إلى التمويه في الخلفية، يؤدي شعاع التمويه الذي يبلغ 20 بكسل إلى إنشاء تأثير جيد لعمق المجال، في حين يؤدي شعاع التمويه الذي يبلغ 80 بكسل في الخلفية إلى إنشاء تأثير جيد للزجاج المموّه. تجنَّب استخدام أقطار التمويه أكبر من 150 بكسل، لأنّ ذلك سيؤثر بشكل كبير في الأداء.
لتحقيق تأثير التمويه المطلوب وزيادة إمكانية القراءة، اختَر قيمة شعاع التمويه مصحوبة بطبقة شفافة من اللون.
تعتيم الخلفية
استخدِم ميزة التمويه في الخلفية على النوافذ العائمة لإنشاء تأثير خلفية للنافذة، وهو صورة تمويهية للمحتوى الأساسي. لإضافة خلفية مموَّهة للنافذة، اتّبِع الخطوات التالية:
استخدِم Window#setBackgroundBlurRadius(int) لتحديد شعاع تمويه الخلفية. أو في مظهر النافذة، اضبط R.attr.windowBackgroundBlurRadius.
اضبط R.attr.windowIsTranslucent على true لجعل النافذة شفافة. يتم رسم التمويه تحت سطح النافذة، لذا يجب أن تكون النافذة شفافة للسماح بظهور التمويه.
يمكنك اختياريًا استدعاء Window#setBackgroundDrawableResource(int) لإضافة عنصر قابل للرسم لخلفية نافذة مستطيلة بلون شفاف. أو في مظهر النافذة، اضبط R.attr.windowBackground.
بالنسبة إلى النافذة ذات الزوايا المستديرة، حدِّد الزوايا المستديرة لل المنطقة المموّهة من خلال ضبط ShapeDrawable مع زوايا مستديرة كعنصر قابل للرسم لخلفية النافذة.
حالات تم تفعيل التمويه فيها وغير مفعَّلة يُرجى الرجوع إلى قسم إرشادات استخدام ميزة التمويه في النوافذ في التطبيقات لمزيد من المعلومات.
تمويه الخلفية
يؤدي التمويه في الخلف إلى تمويه الشاشة بأكملها خلف النافذة. يُستخدَم هذا التأثير لتوجيه انتباه المستخدم إلى محتوى النافذة من خلال تمويه أي محتوى على الشاشة خلف النافذة.
لتمويه المحتوى الذي يظهر خلف نافذتك، اتّبِع الخطوات التالية:
أضِف
FLAG_BLUR_BEHIND
إلى علامات النوافذ لتفعيل ميزة التمويه في الخلف. أو في مظهر النافذة، اضبط R.attr.windowBlurBehindEnabled.اتصل بالرقم
WindowManager.LayoutParams#setBlurBehindRadius
لتحديد التمويه في نطاق خلفية. أو في مظهر النافذة، اضبط R.attr.windowBlurBehindRadius.اختياريًا، اختَر مقدار سمة تكميليًا.
حالات تم تفعيل التمويه فيها وغير مفعَّلة يُرجى الرجوع إلى قسم إرشادات استخدام ميزة التمويه في النوافذ في التطبيقات لمزيد من المعلومات.
إرشادات لاستخدام ميزة التمويه في النوافذ في التطبيقات
يعتمد توفّر ميزة التمويه في النوافذ على ما يلي:
إصدار Android: لا تتوفّر واجهات برمجة التطبيقات الخاصة بميزة تمويه النوافذ إلا على الإصدار 12 من Android والإصدارات الأحدث. تحقَّق من حزمة تطوير البرامج (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>
المصنّعون الأصليون للأجهزة والشركاء
لتفعيل ميزة التمويه على النوافذ على أحد الأجهزة، على المصنّع الأصلي للجهاز الإفصاح عن أنّ الجهاز يتوافق مع ميزة التمويه على النوافذ.
لمعرفة ما إذا كان جهازك متوافقًا مع ميزة التمويه في النوافذ، اتّبِع الخطوات التالية:
تأكَّد من أنّ الجهاز يمكنه تحمّل عبء وحدة معالجة الرسومات الإضافية. قد لا تتمكّن الأجهزة المنخفضة الأداء من التعامل مع هذا الحمل الإضافي، ما قد يؤدي إلى إسقاط اللقطات. لا تفعِّل ميزة تمويه النوافذ إلا على الأجهزة التي تم اختبارها والتي تتضمّن وحدة معالجة رسومات كافية.
إذا كان لديك محرّك عرض مخصّص، تأكّد من أنّ محرّك العرض ينفّذ منطق التمويه. محرّك العرض التلقائي في Android 12 ينفّذ منطق التمويه في
BlurFilter.cpp
.
بعد التأكّد من أنّ جهازك متوافق مع ميزة تمويه النوافذ، اضبط ما يلي في
Surface Flinger sysprop
:
PRODUCT_VENDOR_PROPERTIES += \
ro.surface_flinger.supports_background_blur=1
التحقُّق
للتأكّد من أنّ نافذة تطبيقك تعالج بشكلٍ سليم عند التبديل بين حالتَي تفعيل التمويه وعدم تفعيله، اتّبِع الخطوات التالية:
افتح واجهة المستخدم التي تتضمّن التمويه.
فعِّل أو أوقِف تمويه النوافذ من خلال تفعيل تمويه النوافذ وإيقافه.
تأكَّد من أنّ واجهة مستخدم النافذة تتغيّر من حالة التمويه إلى الحالة العادية والعكس على النحو المتوقّع.
تفعيل ميزة "تمويه النافذة" وإيقافها
لاختبار كيفية عرض واجهة مستخدم النافذة مع تأثير التمويه، يمكنك تفعيل التمويه أو إيقافه باستخدام إحدى الطريقتَين التاليتَين:
من "خيارات المطوّرين":
الإعدادات -> النظام -> خيارات المطوّرين -> العرض المُسرَّع بالأجهزة -> السماح بتمويهات على مستوى النافذة
من وحدة التحكّم الطرفية على جهاز تم إجراء عملية الجذر عليه:
adb shell wm disable-blur 1 # 1 disables window blurs, 0 allows them
لمعرفة ما إذا كان جهاز Android 12 أو الإصدارات الأحدث متوافقًا مع ميزة التمويه في النوافذ وما إذا كانت هذه الميزة مفعَّلة حاليًا، يمكنك تشغيل ملف APK
adb shell wm disable-blur
على جهاز مزوّد بإذن الوصول إلى الجذر.
تحديد المشاكل وحلّها
يمكنك استخدام ما يلي كدليل لتحديد المشاكل وحلّها أثناء عملية التحقّق.
لم يتم رسم أي تمويه
تأكَّد من أنّ ميزة التمويه مفعَّلة حاليًا وأنّ جهازك متوافق معها. راجِع مقالة تفعيل ميزة "تمويه النافذة" وإيقافها.
تأكَّد من ضبط لون خلفية نافذة شفاف. يخفي لون خلفية النافذة المعتم المنطقة المموّهة.
الجهاز الاختباري لا يتيح تمويه النوافذ
- اختبِر تطبيقك على محاكي Android 12. لإعداد محاكي Android، يُرجى الاطّلاع على مقالة إعداد محاكي Android. يتوافق التمويه في النوافذ مع أي جهاز Android افتراضي تنشئه باستخدام المحاكي.
لا تحتوي على زوايا دائرية
- اضبط عنصرًا قابلاً للرسم لخلفية النافذة لتحديد الزوايا المستديرة. يحدِّد هذا العنصر القابل للرسم مخطّط المنطقة المموّهة.
لا يؤدي تعديل خيارات المطوّرين إلى تفعيل التمويهات
- تحقَّق مما إذا كان الجهاز في وضع توفير شحن البطارية أو ما إذا كان يستخدم وضع النفق للوسائط المتعددة. قد يتم أيضًا إيقاف تمويه النوافذ أثناء تشغيل الفيديو على بعض أجهزة التلفزيون.
تمويه الخلفية مرسومًا على الشاشة بالكامل، وليس ضمن حدود النافذة
تحقَّق من android:windowIsFloating للتأكّد من وضع علامة على نافذتك على أنّها عائمة.
تأكَّد من ضبط عنصر قابل للرسم لخلفية النافذة. يحدِّد هذا الإعداد المخطط الخارجي لمنطقة التمويه.
لا يتم تطبيق التعديلات الواردة من المستمع على الشاشة.
- قد يتم تطبيق تعديلات المستمع على نسخة قديمة من النافذة. تحقَّق مما إذا كانت النافذة يتم إغلاقها وإعادة إنشائها باستخدام تعديل العميل المناسب.