عرض المحتوى من الحافة إلى الحافة في المشاهدات

جرِّب طريقة Compose
‫Jetpack Compose هي مجموعة أدوات واجهة المستخدم المقترَحة لنظام Android. تعرَّف على كيفية استخدام ميزة "العرض حتى حافة الشاشة" في Compose.

عند استهداف الإصدار 35 من حزمة تطوير البرامج (SDK) أو إصدار أحدث على جهاز يعمل بالإصدار 15 من نظام التشغيل Android أو إصدار أحدث، يتم عرض تطبيقك من "حافة الشاشة إلى حافة الشاشة". تمتد النافذة على كامل عرض الشاشة وارتفاعها من خلال الرسم خلف أشرطة النظام. تشمل أشرطة النظام شريط الحالة وشريط العنوان وشريط التنقّل.

تحتوي العديد من التطبيقات على شريط التطبيق العلوي. يجب أن يمتد شريط التطبيق العلوي إلى الحافة العلوية من الشاشة ويظهر خلف شريط الحالة. يمكن لشريط التطبيق العلوي أن يتقلّص اختياريًا إلى ارتفاع شريط الحالة عند تمرير المحتوى.

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

الشكل 1. أشرطة النظام في تنسيق "العرض حتى حافة الشاشة"

عند تنفيذ تنسيق "العرض حتى حافة الشاشة" في تطبيقك، ضَع في اعتبارك ما يلي:

  1. تفعيل ميزة "العرض حتى حافة الشاشة"
  2. تنفيذ تنسيقات تكيُّفية لتحسين تجربة المستخدم على عوامل الشكل المختلفة
  3. التعامل مع أي تداخلات مرئية
  4. عرض حواجز خلف أشرطة النظام
مثال على الصور خلف شريط الحالة
الشكل 2. مثال على الصور خلف شريط الحالة

تفعيل ميزة "العرض حتى حافة الشاشة"

إذا كان تطبيقك يستهدف الإصدار 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 بواسطة شريط التنقّل:

مثال على تنفيذ ميزة "من الحافة إلى الحافة"، ولكن شريط التنقّل يغطّي زر الإجراء الرئيسي (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:

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

ينطبق الأمر نفسه على وضع التنقّل بالإيماءات، كما هو موضّح في الشكل 5:

العرض بملء الشاشة مع التنقّل بالإيماءات
الشكل 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:

مثال على مساحات إيماءات نظام التشغيل الداخلية
الشكل 6. الحواف الداخلية لإيماءة نظام التشغيل

على غرار الحواف الداخلية لأشرطة النظام، يمكنك تجنُّب التداخل مع الحواف الداخلية لإيماءة نظام التشغيل باستخدام getInsets(int) مع WindowInsetsCompat.Type.systemGestures().

استخدِم هذه الحواف الداخلية لنقل طرق العرض القابلة للتمرير سريعًا أو إضافة مساحة لها بعيدًا عن الحواف. تشمل حالات الاستخدام الشائعة الأوراق السفلية، التمرير سريعًا في الألعاب واللوحات الدائرية التي تم تنفيذها باستخدام ViewPager2.

في الإصدار 10 من نظام التشغيل Android أو الإصدارات الأحدث، تحتوي الحواف الداخلية لإيماءة النظام على حافة داخلية سفلية لإيماءة الشاشة الرئيسية، وحافة داخلية يمنى ويسرى لإيماءات الرجوع:

مثال على قياسات موضع إدخال إيماءة النظام
الشكل 7. قياسات الحواف الداخلية لإيماءة نظام التشغيل

يوضّح مثال الرمز التالي كيفية تنفيذ الحواف الداخلية لإيماءة نظام التشغيل:

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 Design

تتعامل العديد من مكوّنات Material Design المستندة إلى طرق العرض في Android (‫com.google.android.material) تلقائيًا مع الحواف الداخلية، بما في ذلك BottomAppBar، BottomNavigationView، NavigationRailView وNavigationView

ومع ذلك، AppBarLayout لا تتعامل تلقائيًا مع الحواف الداخلية. أضِف android:fitsSystemWindows="true" للتعامل مع الحواف الداخلية العلوية.

تعرَّف على كيفية التعامل مع الحواف الداخلية باستخدام مكوّنات Material Design في Compose.

إرسال الحواف الداخلية المتوافقة مع الأنظمة القديمة

لإيقاف إرسال الحواف الداخلية إلى طرق العرض الفرعية وتجنُّب إضافة مساحة إضافية، يمكنك استخدام الحواف الداخلية باستخدام الثابت WindowInsetsCompat.CONSUMED. ومع ذلك، على الأجهزة التي تعمل بالإصدار 10 من نظام التشغيل Android (مستوى واجهة برمجة التطبيقات 29 والإصدارات الأقدم)، لا يتم إرسال المساحات الداخلية إلى طرق العرض الشقيقة بعد استدعاء WindowInsetsCompat.CONSUMED، ما قد يؤدي إلى تداخل مرئي غير مقصود.

مثال على إرسال غير صحيح لعمليات الإدراج
الشكل 8. مثال على إرسال الحواف الداخلية بشكل غير صحيح لا يتم إرسال الحواف الداخلية إلى طرق العرض الشقيقة بعد أن تستخدم ViewGroup 1 الحواف الداخلية على الإصدار 10 من نظام التشغيل Android (المستوى 29 لواجهة برمجة التطبيقات) والإصدارات الأقدم، ما يؤدي إلى تداخل TextView 2 مع شريط التنقّل في النظام. ومع ذلك، يتم إرسال المساحات الداخلية إلى طرق العرض الشقيقة على الإصدار 11 من نظام التشغيل Android (مستوى واجهة برمجة التطبيقات 30) والإصدارات الأحدث، كما هو متوقّع.

للتأكّد من إرسال الحواف الداخلية إلى طرق العرض الشقيقة لجميع إصدارات Android المتوافقة، استخدِم ViewGroupCompat#installCompatInsetsDispatch قبل استخدام الحواف الداخلية، وهو متاح على AndroidX Core وCore-ktx 1.16.0-alpha01 والإصدارات الأحدث.

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);
مثال على إرسال مساحة العرض الثابتة
الشكل 9. إرسال المساحات الداخلية بشكل صحيح بعد استدعاء ViewGroupCompat#installCompatInsetsDispatch.

الوضع المجسم

من الأفضل تجربة بعض المحتوى بملء الشاشة، ما يمنح المستخدم تجربة أكثر غامرة. يمكنك إخفاء أشرطة النظام في الوضع المجسم باستخدام مكتبتَي 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 وإلا سيتم تطبيق حاجز شفاف جزئيًا.

إنشاء أشرطة نظام شفافة جزئيًا

لإنشاء شريط حالة شفاف جزئيًا، اتّبِع الخطوات التالية:

  1. حدِّث تبعية androidx-core إلى الإصدار 1.16.0-beta01 أو إصدار أحدث
  2. غلِّف تنسيق XML في androidx.core.view.insets.ProtectionLayout وعيِّن معرّفًا.
  3. يمكنك الوصول إلى 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 مختلفة بألوان مختلفة للوحة القائمة ولوحة التفاصيل.

الشكل 1. حماية التدرّج بألوان مختلفة

لا تنشئ شريط التنقّل بالإيماءات الشفاف جزئيًا. لإنشاء شريط تنقّل شفاف جزئيًا باستخدام ثلاثة أزرار، نفِّذ أحد الإجراءَين التاليَين:

  • إذا كان التنسيق مغلّفًا في ProtectionView، يمكنك تمرير ColorProtection أو GradientProtection إضافية إلى الطريقة setProtections. قبل إجراء ذلك، تأكَّد من أنّ window.isNavigationBarContrastEnforced = false.
  • بخلاف ذلك، اضبط 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);
            }
        }
    }
    ...
}

مراجع إضافية

راجِع المراجع التالية لمزيد من المعلومات عن استخدام ميزة "العرض حتى حافة الشاشة".

المدوّنات

التصميم

المستندات الأخرى

الفيديوهات