إنشاء تخطيط على تفاصيل القائمة

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

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

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

تنفيذ نمط "عرض على شكل قائمة مع تفاصيل" باستخدام NavigableListDetailPaneScaffold

‫NavigableListDetailPaneScaffold هي دالة مركّبة تسهّل تنفيذ عرض على شكل قائمة مع تفاصيل في Jetpack Compose. فهي تلتف حول ListDetailPaneScaffold وتضيف ميزة التنقّل المضمّنة والصور المتحركة لإيماءة إظهار شاشة الرجوع.

يتيح عرض على شكل قائمة مع تفاصيل ما يصل إلى ثلاث لوحات:

  1. لوحة القائمة: تعرض مجموعة من العناصر.
  2. جزء التفاصيل: يعرض تفاصيل العنصر المحدّد.
  3. اللوحة الإضافية (اختيارية): توفّر سياقًا إضافيًا عند الحاجة.

يتكيف الهيكل بناءً على حجم النافذة:

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

تحديد الاعتماديات

‫NavigableListDetailPaneScaffold هو جزء من مكتبة التنقّل التكيُّفي في Material 3.

أضِف الاعتماديات الثلاث التالية ذات الصلة إلى ملف build.gradle لتطبيقك أو وحدتك:

Kotlin

implementation("androidx.compose.material3.adaptive:adaptive")
implementation("androidx.compose.material3.adaptive:adaptive-layout")
implementation("androidx.compose.material3.adaptive:adaptive-navigation")

أنيق

implementation 'androidx.compose.material3.adaptive:adaptive'
implementation 'androidx.compose.material3.adaptive:adaptive-layout'
implementation 'androidx.compose.material3.adaptive:adaptive-navigation'
  • adaptive: وحدات أساسية منخفضة المستوى، مثل HingeInfo وPosture
  • ‫adaptive-layout: التنسيقات التكيّفية، مثل ListDetailPaneScaffold وSupportingPaneScaffold
  • ‫adaptive-navigation: دوال مركّبة للتنقّل داخل الأجزاء وفي ما بينها، بالإضافة إلى تنسيقات تكيُّفية تتيح التنقّل تلقائيًا، مثل NavigableListDetailPaneScaffold وNavigableSupportingPaneScaffold

تأكَّد من أنّ مشروعك يتضمّن الإصدار 1.1.0-beta1 من compose-material3-adaptive أو إصدارًا أحدث.

الموافقة على إيماءة إظهار شاشة الرجوع التنبؤية

لتفعيل الصور المتحركة لإيماءة إظهار شاشة الرجوع في Android 15 أو الإصدارات الأقدم، عليك الموافقة على دعم إيماءة إظهار شاشة الرجوع. للموافقة، أضِف android:enableOnBackInvokedCallback="true" إلى علامة <application> أو علامات <activity> الفردية ضمن ملف AndroidManifest.xml. لمزيد من المعلومات، يُرجى الاطّلاع على مقالة تفعيل إيماءة إظهار شاشة الرجوع.

عندما يستهدف تطبيقك الإصدار 16 من نظام التشغيل Android (مستوى واجهة برمجة التطبيقات 36) أو الإصدارات الأحدث، يتم تفعيل ميزة "إيماءة إظهار شاشة الرجوع" تلقائيًا.

الاستخدام الأساسي

نفِّذ NavigableListDetailPaneScaffold على النحو التالي:

  1. استخدِم فئة تمثّل المحتوى المحدّد. استخدِم فئة Parcelable لإتاحة حفظ عنصر القائمة المحدّد واستعادته. استخدِم المكوّن الإضافي kotlin-parcelize لإنشاء الرمز نيابةً عنك.
  2. أنشئ ThreePaneScaffoldNavigator باستخدام rememberListDetailPaneScaffoldNavigator.

يُستخدَم هذا المتصفّح للتنقّل بين القائمة والتفاصيل والأقسام الإضافية. من خلال تعريف نوع عام، يتتبّع المتصفّح أيضًا حالة السقالة (أي MyItem الذي يتم عرضه). بما أنّ هذا النوع قابل للتجزئة، يمكن حفظ الحالة واستعادتها من خلال أداة التنقّل للتعامل تلقائيًا مع تغييرات الإعدادات.

  1. مرِّر أداة التنقّل إلى الدالة المركّبة NavigableListDetailPaneScaffold.

  2. أضِف تنفيذ لوحة القائمة إلى NavigableListDetailPaneScaffold. استخدِم AnimatedPane لتطبيق الحركات التلقائية للّوحة أثناء التنقّل. بعد ذلك، استخدِم ThreePaneScaffoldNavigator للانتقال إلى جزء التفاصيل، ListDetailPaneScaffoldRole.Detail، وعرض العنصر الذي تم تمريره.

  3. يُرجى تضمين تنفيذ جزء التفاصيل في NavigableListDetailPaneScaffold.

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

  1. يمكنك تغيير defaultBackBehavior في NavigableListDetailPaneScaffold. يستخدم "NavigableListDetailPaneScaffold" تلقائيًا "PopUntilScaffoldValueChange" لـ "defaultBackBehavior".

إذا كان تطبيقك يتطلّب نمطًا مختلفًا للتنقّل للخلف، يمكنك إلغاء هذا السلوك من خلال تحديد خيار BackNavigationBehavior آخر.

خيارات BackNavigationBehavior

يستخدم القسم التالي مثالاً لتطبيق بريد إلكتروني يحتوي على قائمة برسائل البريد الإلكتروني في جزء واحد وعرض تفصيلي في الجزء الآخر.

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

انظر الأمثلة التالية:

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

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

رسم توضيحي يعرض تغييرات قيمة التنقل عبر لوحات تخطيط مختلفة.
PopUntilContentChange

يمنح هذا السلوك الأولوية للمحتوى المعروض. إذا عرضت العنصر 1 ثم العنصر 2، سيؤدي الضغط على زر الرجوع إلى العودة إلى العنصر 1، بغض النظر عن التنسيق.

انظر الأمثلة التالية:

  • متعدد الأجزاء: يمكنك عرض العنصر 1 في جزء التفاصيل، ثم النقر على العنصر 2 في القائمة. يتم تعديل جزء التفاصيل. سيؤدي الضغط على زر الرجوع إلى استعادة جزء التفاصيل إلى العنصر 1.
  • اللوحة الواحدة: يتم عرض المحتوى نفسه.

استخدِم هذا الخيار عندما يتوقّع المستخدم العودة إلى المحتوى الذي تم عرضه سابقًا من خلال إجراء الرجوع.

الانتقال بين جزأي التفاصيل
PopUntilCurrentDestinationChange

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

انظر الأمثلة التالية:

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

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

التنقّل بين لوحتَي التفاصيل والقائمة
PopLatest

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

بعد تنفيذ هذه الخطوات، من المفترض أن يظهر الرمز على النحو التالي:

NavigableListDetailPaneScaffold(
    navigator = navigator,
    listPane = {
        AnimatedPane {
            ListContent(
                words = sampleWords,
                selectionState = navigator.currentDestination?.contentKey?.let {
                    SelectionVisibilityState.ShowSelection(it)
                } ?: SelectionVisibilityState.NoSelection,
                onWordClick = { word ->
                    scope.launch {
                        navigator.navigateTo(ListDetailPaneScaffoldRole.Detail, word)
                    }
                },
                animatedVisibilityScope = this@AnimatedPane,
                sharedTransitionScope = this@SharedTransitionLayout
            )
        }
    },
    detailPane = {
        AnimatedPane {
            DetailContent(
                definedWord = navigator.currentDestination?.contentKey,
                animatedVisibilityScope = this@AnimatedPane,
                sharedTransitionScope = this@SharedTransitionLayout,
                onClosePane = {
                    scope.launch {
                        navigator.navigateBack(
                            backNavigationBehavior = BackNavigationBehavior.PopUntilScaffoldValueChange
                        )

                    }
                }
            )
        }
    }