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

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

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

لوحة تفاصيل معروضة بجانب صفحة القائمة
الشكل 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'
  • الوحدات التكيُّفية: الوحدات الأساسية ذات المستوى المنخفض، مثل HingeInfo و Posture
  • adaptive-layout: التنسيقات التكيُّفية، مثل ListDetailPaneScaffold و SupportingPaneScaffold
  • التنقّل التكيُّفي: عناصر قابلة للتجميع للتنقّل داخل الأقسام وبينها، بالإضافة إلى التنسيقات التكيُّفية التي تتيح التنقّل تلقائيًا، مثل 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

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

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

val scaffoldNavigator = rememberListDetailPaneScaffoldNavigator<MyItem>()
val scope = rememberCoroutineScope()

NavigableListDetailPaneScaffold(
    navigator = scaffoldNavigator,
    listPane = {
        AnimatedPane {
            MyList(
                onItemClick = { item ->
                    // Navigate to the detail pane with the passed item
                    scope.launch {
                        scaffoldNavigator.navigateTo(
                            ListDetailPaneScaffoldRole.Detail,
                            item
                        )
                    }
                },
            )
        }
    },
    detailPane = {
        AnimatedPane {
            // Show the detail pane content if selected item is available
            scaffoldNavigator.currentDestination?.contentKey?.let {
                MyDetails(it)
            }
        }
    },
)