في Android 12، تتوفّر واجهات برمجة تطبيقات عامة لتنفيذ تأثيرات تمويه النوافذ، مثل تمويه الخلفية وتمويه ما خلف النافذة.
يتم استخدام تمويه النوافذ أو تمويه النوافذ المتقاطعة لتمويه الشاشة خلف النافذة المحددة. هناك نوعان من تمويه النوافذ، ويمكن استخدامهما لتحقيق تأثيرات بصرية مختلفة:
تتيح لك ميزة تمويه الخلفية إنشاء نوافذ بخلفيات مموّهة، ما يمنحها تأثير الزجاج المصقول.
يتيح لك خيار تمويه الخلفية تمويه الشاشة بأكملها خلف نافذة (مربّع حوار)، ما يؤدي إلى إنشاء تأثير عمق المجال.
يمكن استخدام التأثيرَين بشكل منفصل أو معًا، كما هو موضّح في الشكل التالي:
a |
b |
![]() c |
الشكل 1: تمويه الخلفية فقط (أ)، تمويه الخلفية فقط (ب)، تمويه الخلفية وتمويه الخلفية (ج)
تعمل ميزة تمويه النافذة على مستوى النوافذ، ما يعني أنّها تعمل أيضًا عندما يكون هناك تطبيق آخر خلف النافذة. يختلف هذا التأثير عن تأثير عرض التمويه، الذي يموّه المحتوى داخل النافذة نفسها. تُعدّ ميزة "تمويه النوافذ" مفيدة لمربّعات الحوار والبطاقات السفلية والنوافذ العائمة الأخرى.
التنفيذ
مطوّرو التطبيقات
يجب أن يوفّر مطوّرو التطبيقات نصف قطر التمويه لإنشاء تأثير التمويه. يتحكّم نصف قطر التمويه في مدى كثافة التمويه، أي كلما زاد نصف القطر، زادت كثافة التمويه. وتعني قيمة التمويه 0 بكسل عدم وجود تمويه. بالنسبة إلى التمويه في الخلفية، يؤدي استخدام نصف قطر يبلغ 20 بكسل إلى إنشاء تأثير جيد لعمق المجال، بينما يؤدي استخدام نصف قطر تمويه في الخلفية يبلغ 80 بكسل إلى إنشاء تأثير جيد للزجاج المصنفر. تجنَّب استخدام نصف قطر تمويه أعلى من 150 بكسل، لأنّ ذلك سيؤثر بشكل كبير في الأداء.
لتحقيق تأثير التمويه المطلوب وزيادة إمكانية القراءة، اختر قيمة نصف قطر التمويه مكملة بطبقة شفافة من اللون.
تمويه الخلفية
استخدِم ميزة تمويه الخلفية في النوافذ العائمة لإنشاء تأثير خلفية النافذة، وهو عبارة عن صورة مموّهة للمحتوى الأساسي. لإضافة خلفية مموَّهة للنافذة، اتّبِع الخطوات التالية:
يمكنك استدعاء Window#setBackgroundBlurRadius(int) لضبط نصف قطر تمويه الخلفية. أو يمكنك ضبط R.attr.windowBackgroundBlurRadius في مظهر النافذة.
اضبط R.attr.windowIsTranslucent على "صحيح" لجعل النافذة شفافة. يتم رسم التمويه أسفل سطح النافذة، لذا يجب أن تكون النافذة شفافة ليظهر التمويه.
يمكنك اختياريًا استدعاء 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 وحدة بكسل مستقلة الكثافة على النحو التالي:
<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>
المصنّعون الأصليون للأجهزة والشركاء
لتفعيل ميزة تمويه النوافذ على جهاز معيّن، على المصنّع الأصلي للجهاز الإعلان عن أنّ الجهاز يتيح هذه الميزة.
للتحقّق مما إذا كان جهازك يتيح تمويه النوافذ، اتّبِع الخطوات التالية:
تأكَّد من أنّ الجهاز يمكنه التعامل مع الحمل الإضافي على وحدة معالجة الرسومات. قد لا تتمكّن الأجهزة المنخفضة المواصفات من التعامل مع الحمل الإضافي، ما قد يؤدي إلى إسقاط اللقطات. لا تفعِّل ميزة تمويه النوافذ إلا على الأجهزة التي تم اختبارها والتي تتضمّن وحدة معالجة رسومات (GPU) ذات طاقة كافية.
إذا كان لديك محرّك عرض مخصّص، تأكَّد من أنّه يطبّق منطق التمويه. يستخدم محرّك العرض التلقائي في 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 أو إصدار أحدث يتيح تمويه
النوافذ وما إذا كان تمويه النوافذ مفعَّلاً حاليًا، يمكنك تشغيل
adb shell wm disable-blur على جهاز جذر.
تحديد المشاكل وحلّها
يمكنك استخدام ما يلي كدليل لتحديد المشاكل وحلّها أثناء عملية التحقّق.
لم يتم رسم أي تمويه
تأكَّد من أنّ ميزة التمويه مفعَّلة حاليًا وأنّ جهازك متوافق معها. يُرجى الرجوع إلى مقالة تفعيل ميزة "تمويه النافذة" وإيقافها.
تأكَّد من ضبط لون خلفية نافذة شفافة. يخفي لون خلفية النافذة المعتمة المنطقة المموّهة.
لا يتيح جهاز الاختبار تمويه النوافذ
- اختبِر تطبيقك على محاكي Android 12. لإعداد Android Emulator، يُرجى الرجوع إلى مقالة إعداد Android Emulator. يتيح أي جهاز افتراضي متوافق مع Android يتم إنشاؤه باستخدام المحاكي استخدام ميزة تمويه النوافذ.
بدون زوايا مستديرة
- اضبط خلفية نافذة قابلة للرسم لتحديد الزوايا الدائرية. يحدّد هذا العنصر القابل للرسم المخطط التفصيلي للمنطقة المموّهة.
تعديل خيار المطوّرين لا يفعّل ميزة التمويه
- تحقَّق مما إذا كان الجهاز في وضع "توفير شحن البطارية" أو ما إذا كان يستخدم نفق الوسائط المتعددة. على بعض أجهزة التلفزيون، قد يتم أيضًا إيقاف تمويه النوافذ أثناء تشغيل الفيديو.
يتم رسم تمويه الخلفية بملء الشاشة، وليس ضمن حدود النافذة
تحقَّق من android:windowIsFloating للتأكّد من وضع علامة على النافذة على أنّها عائمة.
تأكَّد من ضبط خلفية نافذة قابلة للرسم. يحدّد هذا الإعداد مخطط منطقة التمويه.
لا يتم تطبيق التحديثات من المستمع على الشاشة
- قد يتم تطبيق تعديلات المستمع على مثيل نافذة قديم. يُرجى التحقّق مما إذا كان يتم إغلاق النافذة وإعادة إنشائها باستخدام التعديل الصحيح للمستمع.
