بعد استهداف الإصدار 35 من حزمة تطوير البرامج (SDK) أو إصدار أحدث على جهاز يعمل بالإصدار 15 من نظام التشغيل Android أو إصدار أحدث، سيتم عرض تطبيقك حتى حافة الشاشة. يمتدّ حجم النافذة على كامل عرض الشاشة وارتفاعها من خلال الرسم خلف أشرطة النظام. تشمل أشرطة النظام شريط الحالة وشريط العنوان وشريط التنقّل.
تتضمّن العديد من التطبيقات شريط تطبيق علويًا. يجب أن يمتد شريط التطبيق العلوي إلى الحافة العلوية من الشاشة وأن يظهر خلف شريط الحالة. يمكنك اختياريًا تصغير شريط التطبيق العلوي ليصبح بارتفاع شريط الحالة عند تمرير المحتوى.
يحتوي العديد من التطبيقات أيضًا على شريط تطبيق سفلي أو شريط تنقّل سفلي. يجب أن تمتد هذه الأشرطة أيضًا إلى الحافة السفلية من الشاشة وأن تظهر خلف شريط التنقل. وفي ما عدا ذلك، يجب أن تعرض التطبيقات محتوى قابلاً للتمرير خلف شريط التنقّل.
عند تنفيذ تصميم من الحافة إلى الحافة في تطبيقك، يجب مراعاة ما يلي:
- تفعيل ميزة "العرض حتى حافة الشاشة"
- استخدام تصاميم متجاوبة لتحسين تجربة المستخدم على مختلف عوامل الشكل
- التعامل مع أي تداخلات مرئية
- ننصحك بعرض حاجبات خلف أشرطة النظام
تفعيل ميزة "العرض حتى حافة الشاشة"
إذا كان تطبيقك يستهدف الإصدار 35 من حزمة تطوير البرامج (SDK) أو إصدارًا أحدث، سيتم تفعيل وضع "من الحافة إلى الحافة" تلقائيًا على أجهزة Android 15 أو الإصدارات الأحدث.
لتفعيل ميزة "العرض حتى حافة الشاشة" على إصدارات Android السابقة، عليك استدعاء enableEdgeToEdge يدويًا في onCreate من Activity.
Kotlin
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
WindowCompat.enableEdgeToEdge(window)
...
}
Java
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
WindowCompat.enableEdgeToEdge(getWindow());
...
}
بشكلٍ تلقائي، يجعل enableEdgeToEdge() أشرطة النظام شفافة، باستثناء وضع التنقّل باستخدام ثلاثة أزرار حيث يتم وضع حاجب شفاف على شريط التنقّل. يتم تعديل ألوان رموز النظام والطبقة الشفافة استنادًا إلى المظهر الفاتح أو الداكن للنظام.
لتفعيل ميزة "العرض حتى حافة الشاشة" في تطبيقك بدون استخدام الدالة enableEdgeToEdge()، راجِع إعداد ميزة "العرض حتى حافة الشاشة" يدويًا.
التعامل مع التداخلات باستخدام الحواف الداخلية
قد يتم عرض بعض طرق العرض في تطبيقك خلف أشرطة النظام، كما هو موضّح في الشكل 3.
يمكنك معالجة التداخلات من خلال التفاعل مع اللوحات المضمّنة التي تحدّد أجزاء الشاشة التي تتقاطع مع واجهة مستخدم النظام، مثل شريط التنقّل أو شريط الحالة. قد يعني التقاطع العرض فوق المحتوى، ولكن يمكن أن يتيح أيضًا لتطبيقك معرفة الإيماءات التي ينفّذها المستخدم على النظام.
في ما يلي أنواع الحواف الداخلية التي تنطبق على عرض تطبيقك من الحافة إلى الحافة:
فواصل أشرطة النظام: هي الأنسب للعناصر القابلة للنقر والتي يجب ألا تحجبها أشرطة النظام.
حواف الصورة المقطوعة للشاشة: للمناطق التي قد تكون فيها صورة مقطوعة للشاشة بسبب شكل الجهاز
مواضع إدخال إيماءات النظام: لمساحات التنقّل بالإيماءات التي يستخدمها النظام والتي لها الأولوية على تطبيقك
فواصل أشرطة النظام
تُعدّ هوامش شريط النظام النوع الأكثر استخدامًا من الهوامش. وهي تمثّل المساحة التي تظهر فيها واجهة مستخدم النظام على المحور Z فوق تطبيقك، ويُفضّل استخدامها لنقل أو توسيع طرق العرض في تطبيقك التي يمكن النقر عليها والتي يجب ألا تحجبها أشرطة النظام بصريًا.
على سبيل المثال، تم حجب زر الإجراء العائم (FAB) في الشكل 3 جزئيًا بواسطة شريط التنقّل:
لتجنُّب هذا النوع من التداخل المرئي في وضع الإيماءات أو وضع الأزرار، يمكنك زيادة هوامش العرض باستخدام
getInsets(int)
مع
WindowInsetsCompat.Type.systemBars().
يوضّح مثال الرمز البرمجي التالي كيفية تنفيذ هوامش نظام الأشرطة:
Kotlin
ViewCompat.setOnApplyWindowInsetsListener(fab) { v, windowInsets -> val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()) // Apply the insets as a margin to the view. This solution sets // only the bottom, left, and right dimensions, but you can apply whichever // insets are appropriate to your layout. You can also update the view padding // if that's more appropriate. v.updateLayoutParams<MarginLayoutParams> { leftMargin = insets.left bottomMargin = insets.bottom rightMargin = insets.right } // Return CONSUMED if you don't want the window insets to keep passing // down to descendant views. WindowInsetsCompat.CONSUMED }
Java
ViewCompat.setOnApplyWindowInsetsListener(fab, (v, windowInsets) -> { Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()); // Apply the insets as a margin to the view. This solution sets only the // bottom, left, and right dimensions, but you can apply whichever insets are // appropriate to your layout. You can also update the view padding if that's // more appropriate. MarginLayoutParams mlp = (MarginLayoutParams) v.getLayoutParams(); mlp.leftMargin = insets.left; mlp.bottomMargin = insets.bottom; mlp.rightMargin = insets.right; v.setLayoutParams(mlp); // Return CONSUMED if you don't want the window insets to keep passing // down to descendant views. return WindowInsetsCompat.CONSUMED; });
إذا طبّقت هذا الحلّ على المثال الموضّح في الشكل 3، لن يحدث أي تداخل مرئي في وضع الزر، كما هو موضّح في الشكل 4:
ينطبق الأمر نفسه على وضع التنقّل بالإيماءات، كما هو موضّح في الشكل 5:
صورة مقطوعة للشاشة
تتضمّن بعض الأجهزة فتحات في الشاشة. عادةً ما يكون موضع القطع في أعلى الشاشة ويتم تضمينه في شريط الحالة. عندما تكون شاشة الجهاز في الوضع الأفقي، قد يكون موضع القطع على الحافة العمودية. استنادًا إلى المحتوى الذي يعرضه تطبيقك على الشاشة، عليك إضافة مساحة متروكة لتجنُّب صورة مقطوعة للشاشة، لأنّ التطبيقات سترسم تلقائيًا في صورة مقطوعة للشاشة.
على سبيل المثال، تعرض العديد من شاشات التطبيقات قائمة بالعناصر. لا تحجب عناصر القائمة بواسطة صورة مقطوعة للشاشة أو أشرطة النظام.
Kotlin
ViewCompat.setOnApplyWindowInsetsListener(binding.recyclerView) { v, insets -> val bars = insets.getInsets( WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.displayCutout() ) v.updatePadding( left = bars.left, top = bars.top, right = bars.right, bottom = bars.bottom, ) WindowInsetsCompat.CONSUMED }
Java
ViewCompat.setOnApplyWindowInsetsListener(mBinding.recyclerView, (v, insets) -> { Insets bars = insets.getInsets( WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.displayCutout() ); v.setPadding(bars.left, bars.top, bars.right, bars.bottom); return WindowInsetsCompat.CONSUMED; });
حدِّد قيمة WindowInsetsCompat من خلال إجراء عملية أو المنطقية على أشرطة النظام وأنواع الفتحات المعروضة.
اضبط قيمة clipToPadding على RecyclerView لكي يتم تمرير المساحة المتروكة مع عناصر القائمة. يسمح ذلك للعناصر بالانتقال إلى خلف أشرطة النظام عندما يتنقّل المستخدم، كما هو موضّح في المثال التالي.
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
إضافات إيماءات نظام التشغيل
تمثّل مساحات إدخال إيماءات نظام التشغيل الداخلية مناطق النافذة التي تكون فيها الأولوية لإيماءات نظام التشغيل على تطبيقك. وتظهر هذه المناطق باللون البرتقالي في الشكل 6:
كما هو الحال مع هوامش شريط النظام، يمكنك تجنُّب تداخل هوامش إيماءات نظام التشغيل باستخدام getInsets(int) مع WindowInsetsCompat.Type.systemGestures().
استخدِم هذه الهوامش الداخلية لنقل طرق العرض القابلة للتمرير السريع أو إضافة مساحة فارغة بينها وبين الحواف. تشمل حالات الاستخدام الشائعة الأوراق السفلية والتمرير السريع في الألعاب وعناصر العرض الدوّارة التي يتم تنفيذها باستخدام ViewPager2.
في نظام التشغيل Android 10 أو الإصدارات الأحدث، تحتوي المساحات الداخلية لإيماءات النظام على مساحة داخلية سفلية لإيماءة الرجوع إلى الشاشة الرئيسية، ومساحة داخلية يمنى ويسرى لإيماءات الرجوع:
يوضّح مثال الرمز البرمجي التالي كيفية تنفيذ هوامش إدخال إيماءات نظام التشغيل:
Kotlin
ViewCompat.setOnApplyWindowInsetsListener(view) { view, windowInsets -> val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemGestures()) // Apply the insets as padding to the view. Here, set all the dimensions // as appropriate to your layout. You can also update the view's margin if // more appropriate. view.updatePadding(insets.left, insets.top, insets.right, insets.bottom) // Return CONSUMED if you don't want the window insets to keep passing down // to descendant views. WindowInsetsCompat.CONSUMED }
Java
ViewCompat.setOnApplyWindowInsetsListener(view, (v, windowInsets) -> { Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemGestures()); // Apply the insets as padding to the view. Here, set all the dimensions // as appropriate to your layout. You can also update the view's margin if // more appropriate. view.setPadding(insets.left, insets.top, insets.right, insets.bottom); // Return CONSUMED if you don't want the window insets to keep passing down // to descendant views. return WindowInsetsCompat.CONSUMED; });
مكوّنات Material
تتعامل العديد من مكوّنات Android Material المستندة إلى طرق العرض (com.google.android.material) تلقائيًا مع الحواف الداخلية، بما في ذلك
BottomAppBar وBottomNavigationView وNavigationRailView وNavigationView.
ومع ذلك، لا يتعامل AppBarLayout مع الحواف الداخلية تلقائيًا. أضِف
android:fitsSystemWindows="true"
للتعامل مع عمليات الإدخال في أعلى الشاشة.
اطّلِع على كيفية التعامل مع المساحات الداخلية باستخدام Material Components في Compose.
إرسال المحتوى المضمّن المتوافق مع الأنظمة القديمة
لإيقاف إرسال المساحات المتروكة إلى طرق العرض الفرعية وتجنُّب إضافة مساحة متروكة كبيرة جدًا، يمكنك استخدام المساحات المتروكة باستخدام الثابت WindowInsetsCompat.CONSUMED. ومع ذلك، على الأجهزة التي تعمل بالإصدار 10 من نظام التشغيل Android (المستوى 29 من واجهة برمجة التطبيقات والإصدارات الأقدم)، لا يتم إرسال المساحات الداخلية إلى العناصر الشقيقة بعد استدعاء WindowInsetsCompat.CONSUMED، ما قد يؤدي إلى تداخل مرئي غير مقصود.
للتأكّد من إرسال الحواف الداخلية إلى العناصر الشقيقة في جميع إصدارات Android المتوافقة، استخدِم ViewGroupCompat#installCompatInsetsDispatch قبل استخدام الحواف الداخلية، وهي متاحة على الإصدار 1.16.0-alpha01 من AndroidX Core وCore-ktx والإصدارات الأحدث.
Kotlin
// Use the i.d. assigned to your layout's root view, e.g. R.id.main val rootView = findViewById(R.id.main) // Call before consuming insets ViewGroupCompat.installCompatInsetsDispatch(rootView)
Java
// Use the i.d. assigned to your layout's root view, e.g. R.id.main LinearLayout rootView = findViewById(R.id.main); // Call before consuming insets ViewGroupCompat.installCompatInsetsDispatch(rootView);
الوضع المجسم
من الأفضل عرض بعض المحتوى في وضع ملء الشاشة، ما يمنح المستخدم تجربة أكثر
انغماسًا. يمكنك إخفاء أشرطة النظام في وضع ملء الشاشة باستخدام المكتبتَين
WindowInsetsController
و
WindowInsetsControllerCompat:
Kotlin
val windowInsetsController = WindowCompat.getInsetsController(window, window.decorView) // Hide the system bars. windowInsetsController.hide(Type.systemBars()) // Show the system bars. windowInsetsController.show(Type.systemBars())
Java
Window window = getWindow(); WindowInsetsControllerCompat windowInsetsController = WindowCompat.getInsetsController(window, window.getDecorView()); if (windowInsetsController == null) { return; } // Hide the system bars. windowInsetsController.hide(WindowInsetsCompat.Type.systemBars()); // Show the system bars. windowInsetsController.show(WindowInsetsCompat.Type.systemBars());
يُرجى الاطّلاع على إخفاء أشرطة النظام في وضع العرض الغامر للحصول على مزيد من المعلومات حول تنفيذ هذه الميزة.
رموز شريط النظام
يضمن استدعاء enableEdgeToEdge تعديل ألوان رموز شريط النظام عند تغيير مظهر الجهاز.
عند استخدام وضع "العرض حتى حافة الشاشة"، قد تحتاج إلى تعديل ألوان رموز شريط النظام يدويًا لكي تتباين مع خلفية تطبيقك. على سبيل المثال، لإنشاء رموز شريط الحالة الفاتحة، اتّبِع الخطوات التالية:
Kotlin
WindowCompat.getInsetsController(window, window.decorView) .isAppearanceLightStatusBars = false
Java
WindowCompat.getInsetsController(window, window.getDecorView()) .setAppearanceLightStatusBars(false);
الحماية من التلاعب بشريط النظام
بعد أن يستهدف تطبيقك الإصدار 35 من حزمة تطوير البرامج (SDK) أو إصدارًا أحدث، سيتم فرض ميزة "العرض حتى حافة الشاشة".
يكون شريط حالة النظام وأشرطة التنقّل بالإيماءات شفافة، بينما يكون شريط التنقّل بثلاثة أزرار شبه شفاف. اتّصِل بالرقم enableEdgeToEdge لجعل هذه الميزة متوافقة مع الأنظمة القديمة.
ومع ذلك، قد لا تعمل الإعدادات التلقائية للنظام في جميع حالات الاستخدام. راجِع إرشادات تصميم أشرطة نظام Android والتصميم من الحافة إلى الحافة لتحديد ما إذا كان يجب استخدام أشرطة نظام شفافة أو شبه شفافة.
إنشاء أشرطة نظام شفافة
يمكنك إنشاء شريط حالة شفاف من خلال استهداف الإصدار 15 من نظام التشغيل Android (الإصدار 35 من حزمة تطوير البرامج (SDK)) أو إصدار أحدث، أو من خلال استدعاء enableEdgeToEdge() باستخدام وسيطات تلقائية للإصدارات السابقة.
يمكنك إنشاء شريط شفاف للتنقّل بالإيماءات من خلال استهداف الإصدار 15 من نظام التشغيل Android أو الإصدارات الأحدث أو من خلال استدعاء enableEdgeToEdge() باستخدام وسيطات تلقائية للإصدارات الأقدم. بالنسبة إلى شريط التنقل الذي يتضمّن ثلاثة أزرار، اضبط قيمة Window.setNavigationBarContrastEnforced على false، وإلا سيتم تطبيق طبقة شفافة.
إنشاء أشرطة نظام شفافة
لإنشاء شريط حالة شبه شفاف، اتّبِع الخطوات التالية:
- تحديث اعتمادية
androidx-coreإلى الإصدار 1.16.0-beta01 أو إصدار أحدث - غلِّف تنسيق XML بالعنصر
androidx.core.view.insets.ProtectionLayoutوأسنِد معرّفًا. - يمكنك الوصول إلى
ProtectionLayoutآليًا لضبط وسائل الحماية، مع تحديد الجانب وGradientProtectionلشريط الحالة.
<androidx.core.view.insets.ProtectionLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/list_protection" android:layout_width="match_parent" android:layout_height="match_parent"> <ScrollView android:id="@+id/item_list" android:clipToPadding="false" android:layout_width="match_parent" android:layout_height="match_parent"> <!--items--> </ScrollView> </androidx.core.view.insets.ProtectionLayout>
findViewById<ProtectionLayout>(R.id.list_protection) .setProtections( listOf( GradientProtection( WindowInsetsCompat.Side.TOP, // Ideally, this is the pane's background color paneBackgroundColor ) ) )
تأكَّد من أنّ قيمة ColorInt التي تم إدخالها في GradientProtection تتطابق مع خلفية المحتوى. على سبيل المثال، قد يتضمّن عرض على شكل قائمة مع تفاصيل معروض على جهاز قابل للطي GradientProtections مختلفة بألوان مختلفة للوحة القائمة ولوحة التفاصيل.
لا تنشئ شريط التنقّل بالإيماءات شبه الشفاف. لإنشاء شريط تنقّل شفاف بثلاثة أزرار، اتّبِع أحد الإجراءَين التاليَين:
- إذا كان التنسيق الخاص بك مضمّنًا في
ProtectionView، يمكنك تمريرColorProtectionأوGradientProtectionإضافيَين إلى طريقةsetProtections. قبل إجراء ذلك، تأكَّد منwindow.isNavigationBarContrastEnforced = false. - بخلاف ذلك، اضبط السمة
window.isNavigationBarContrastEnforced = true. إذا كانت مكالمات تطبيقك التي يتم إجراؤها باستخدامenableEdgeToEdge, window.isNavigationBarContrastEnforced = trueهي الإعداد التلقائي.
نصائح أخرى
ملاحظات إضافية عند التعامل مع الحواف الداخلية
عرض المحتوى القابل للتمرير من الحافة إلى الحافة
تأكَّد من أنّ آخر عنصر في القائمة غير محجوب بواسطة أشرطة النظام في RecyclerView أو NestedScrollView من خلال معالجة الهوامش الداخلية وضبط clipToPadding على false.
يعرض الفيديو التالي RecyclerView مع إيقاف ميزة "العرض من الحافة إلى الحافة" (على اليمين) وتفعيلها (على اليسار):
راجِع مقتطفات الرموز في قسم إنشاء قوائم ديناميكية باستخدام RecyclerView للحصول على عينة تعليمات برمجية.
عرض مربّعات الحوار بملء الشاشة من الحافة إلى الحافة
لجعل مربّع الحوار بملء الشاشة يمتد من الحافة إلى الحافة، استخدِم enableEdgeToEdge في مربّع الحوار.
Kotlin
class MyAlertDialogFragment : DialogFragment() {
override fun onStart(){
super.onStart()
dialog?.window?.let { WindowCompat.enableEdgeToEdge(it) }
}
...
}
Java
public class MyAlertDialogFragment extends DialogFragment {
@Override
public void onStart() {
super.onStart();
Dialog dialog = getDialog();
if (dialog != null) {
Window window = dialog.getWindow();
if (window != null) {
WindowCompat.enableEdgeToEdge(window);
}
}
}
...
}
مراجع إضافية
راجِع المراجع التالية لمزيد من المعلومات حول عرض المحتوى من الحافة إلى الحافة.
المدوّنات
- نصائح بشأن التعامل مع الحواف الداخلية في Android 15
- WindowInsets — أدوات معالجة الأحداث في التنسيقات
التصميم
المستندات الأخرى
الفيديوهات