عرض المحتوى بشكل شامل في تطبيقك

تجربة طريقة ComposeAllowed
Jetpack Compose هي مجموعة أدوات واجهة المستخدم التي ننصح بها لنظام التشغيل Android. تعرَّف على كيفية العمل من الحافة إلى الحافة في Compose.

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

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

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

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

عند تنفيذ تصميم شامل في تطبيقك، يجب مراعاة ما يلي:

  1. تفعيل شاشة العرض الشامل
  2. معالجة أي تداخلات مرئية.
  3. يمكنك عرض أدوات التحديد خلف أشرطة النظام.
مثال على صور خلف شريط الحالة
الشكل 2. مثال على صور خلف شريط الحالة.

تفعيل العرض الشامل

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

لتفعيل ميزة العرض الشامل في إصدارات Android السابقة، عليك إجراء ما يلي:

  1. أضِف تبعية إلى مكتبة androidx.activity في ملف build.gradle لتطبيقك أو وحدتك:

    Kotlin

    dependencies {
        val activity_version = activity_version
        // Java language implementation
        implementation("androidx.activity:activity:$activity_version")
        // Kotlin
        implementation("androidx.activity:activity-ktx:$activity_version")
    }
    

    رائع

    dependencies {
        def activity_version = activity_version
        // Java language implementation
        implementation 'androidx.activity:activity:$activity_version'
        // Kotlin
        implementation 'androidx.activity:activity-ktx:$activity_version'
    }
    
  2. استورِد وظيفة الإضافة enableEdgeToEdge إلى تطبيقك:

يمكنك تفعيل ميزة "التوافق مع حافة" يدويًا من خلال استدعاء enableEdgeToEdge في onCreate من Activity. يجب الاتصال قبل setContentView.

Kotlin

     override fun onCreate(savedInstanceState: Bundle?) {
       enableEdgeToEdge()
       super.onCreate(savedInstanceState)
       ...
     }
   

Java

     @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
       EdgeToEdge.enable(this);
       super.onCreate(savedInstanceState);
       ...
     }
   

يجعل enableEdgeToEdge() أشرطة النظام تلقائيًا، باستثناء وضع التنقّل باستخدام ثلاثة أزرار حيث يظهر زغب شبه شفاف في شريط الحالة. ويتم تعديل ألوان رموز النظام ولقطة الشاشة بناءً على المظهر الفاتح أو الداكن في النظام.

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

لتفعيل ميزة العرض الشامل في تطبيقك بدون استخدام الوظيفة enableEdgeToEdge()، يمكنك الاطّلاع على الإعداد اليدوي للشاشة من الحافة إلى الحافة.

التعامل مع التداخل باستخدام إدراجات داخلية

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

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

في ما يلي أنواع المساحات الداخلية التي تنطبق على عرض تطبيقك بشكل شامل:

  • العناصر الداخلية في أشرطة النظام: هو الأفضل للعروض القابلة للنقر والتي يجب ألا تحجبها أشرطة النظام بصريًا.

  • لوحات صور مقطوعة للشاشة:مخصّصة للمناطق التي قد تظهر فيها صور مقطوعة للشاشة بسبب شكل الجهاز.

  • وحدات إيماءة النظام: لمناطق التنقُّل بالإيماءات التي يستخدمها النظام التي لها الأولوية على تطبيقك.

إدراجات أشرطة النظام

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

على سبيل المثال، زر الإجراء العائم (FAB) في الشكل 3 محجوب جزئيًا بواسطة شريط التنقل:

مثال على التنفيذ من الحافة إلى الحافة، ولكن شريط التنقل يغطي زر الإجراء الرئيسي (FAB)
الشكل 3. يتداخل شريط التنقل مع زر الإجراء الرئيسي (FAB) في تنسيق شامل.

لتجنُّب هذا النوع من التداخل المرئي في وضع الإيماءة أو وضع الزر، يمكنك زيادة هوامش العرض باستخدام 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 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 want the window insets to keep passing
  // down to descendant views.
    return WindowInsetsCompat.CONSUMED;
});

إذا طبقت هذا الحل على المثال الموضح في الشكل 3، فإنه لا ينتج عنه تداخل مرئي في وضع الزر، كما هو موضح في الشكل 4:

شريط تنقل شبه شفاف لا يغطي زر الإجراء الرئيسي (FAB)
الشكل 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) -> {
  WindowInsetsCompat 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;
});

وضع مجسم

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

راجِع مقالة إخفاء أشرطة النظام للوضع المجسم لمزيد من المعلومات حول تطبيق هذه الميزة.

مصادر إضافية

راجِع المراجع التالية للحصول على مزيد من المعلومات حول WindowInsets والتنقّل بالإيماءات وطريقة عمل الإضافات: