تنظيم صفحاتك في مجموعات
يمكنك حفظ المحتوى وتصنيفه حسب إعداداتك المفضّلة.
نمط واجهة المستخدم "قائمة-تفاصيل" هو نمط يتألف من تصميم ذي لوحتَين، تعرض إحداهما قائمة بالعناصر، بينما تعرض الأخرى تفاصيل العناصر المحدّدة من القائمة.
ويكون النمط مفيدًا بشكل خاص للتطبيقات التي توفّر معلومات مفصّلة حول عناصر المجموعات الكبيرة، مثل برنامج البريد الإلكتروني الذي يتضمّن قائمة بالرسائل الإلكترونية والمحتوى المفصّل لكل رسالة إلكترونية.
يمكن أيضًا استخدام نمط العرض "قائمة-تفاصيل" للمسارات الأقل أهمية، مثل تقسيم إعدادات التطبيق المفضّلة إلى قائمة فئات مع الإعدادات المفضّلة لكل فئة في لوحة التفاصيل.
الشكل 1. عند توفّر مساحة كافية على الشاشة، يتم عرض جزء التفاصيل بجانب جزء القائمة.الشكل 2. عندما يكون حجم الشاشة محدودًا، يشغل جزء التفاصيل (بعد اختيار عنصر) المساحة بأكملها.
تنفيذ نمط "القائمة والتفاصيل" باستخدام NavigableListDetailPaneScaffold
NavigableListDetailPaneScaffold هي دالة برمجية قابلة للإنشاء تسهّل تنفيذ تصميم
قائمة وتفاصيل في Jetpack Compose. وهي تتضمّن ListDetailPaneScaffold وتضيف صورًا متحركة مدمجة للتنقّل وإيماءة الرجوع إلى الخلف التنبؤية.
يتيح تصميم قائمة وتفاصيل ما يصل إلى ثلاث لوحات:
لوحة القائمة: تعرض مجموعة من العناصر.
لوحة التفاصيل: تعرض تفاصيل عنصر محدّد.
لوحة إضافية (اختيارية): تقدّم سياقًا إضافيًا عند الحاجة.
يتكيّف الهيكل الأساسي استنادًا إلى حجم النافذة:
في النوافذ الكبيرة، تظهر لوحتا القائمة والتفاصيل جنبًا إلى جنب.
في النوافذ الصغيرة، لا يظهر سوى جزء واحد في كل مرة، ويتم التبديل بين الأجزاء أثناء تنقّل المستخدمين.
التكيّف: الوحدات الأساسية المنخفضة المستوى، مثل HingeInfo وPosture
adaptive-layout: التنسيقات التكيّفية، مثل ListDetailPaneScaffold وSupportingPaneScaffold
adaptive-navigation: عناصر قابلة للإنشاء للتنقّل داخل اللوحات وبينها، بالإضافة إلى التصاميم التكيّفية التي تتيح التنقّل تلقائيًا، مثل NavigableListDetailPaneScaffold وNavigableSupportingPaneScaffold
لتفعيل الصور المتحركة لإيماءة الرجوع التنبؤية في نظام التشغيل Android 15 أو الإصدارات الأقدم، عليك الموافقة على استخدام إيماءة الرجوع التنبؤية. للموافقة، أضِف
android:enableOnBackInvokedCallback="true" إلى علامة <application> أو
علامات <activity> الفردية ضمن ملف AndroidManifest.xml. لمزيد من المعلومات، يُرجى الاطّلاع على مقالة تفعيل إيماءة الرجوع التوقّعية.
بعد أن يستهدف تطبيقك الإصدار 16 من نظام التشغيل Android (المستوى 36 لواجهة برمجة التطبيقات) أو الإصدارات الأحدث، سيتم تفعيل ميزة "الرجوع التوقّعي" تلقائيًا.
الاستخدام الأساسي
نفِّذ الترميز NavigableListDetailPaneScaffold على النحو التالي:
أنشئ ThreePaneScaffoldNavigator باستخدام
rememberListDetailPaneScaffoldNavigator.
يُستخدم شريط التنقّل هذا للتنقّل بين القائمة والتفاصيل والألواح الإضافية. من خلال تعريف نوع عام، يتتبّع أداة التنقّل أيضًا حالة التصميم الأساسي (أي MyItem الذي يتم عرضه). بما أنّ هذا النوع قابل للتجزئة، يمكن لحزمة التنقّل حفظ الحالة واستعادتها للتعامل تلقائيًا مع تغييرات الإعدادات.
مرِّر أداة التنقّل إلى الدالة القابلة للإنشاء NavigableListDetailPaneScaffold.
قدِّم عملية تنفيذ لوحة القوائم إلى
NavigableListDetailPaneScaffold. استخدِم AnimatedPane لتطبيق
حركات الألواح التلقائية أثناء التنقّل. بعد ذلك، استخدِم ThreePaneScaffoldNavigator
للانتقال إلى جزء التفاصيل، ListDetailPaneScaffoldRole.Detail، وعرض
العنصر الذي تم تمريره.
أدرِج تنفيذ لوحة التفاصيل في NavigableListDetailPaneScaffold.
عند اكتمال عملية التنقّل، يحتوي currentDestination على اللوحة التي انتقل إليها تطبيقك، بما في ذلك المحتوى المعروض في اللوحة. السمة contentKey هي النوع نفسه المحدّد في الطلب الأصلي، ما يتيح لك الوصول إلى أي بيانات تحتاج إلى عرضها.
يمكنك اختياريًا تغيير defaultBackBehavior في NavigableListDetailPaneScaffold. تلقائيًا، تستخدم NavigableListDetailPaneScaffoldPopUntilScaffoldValueChange في defaultBackBehavior.
إذا كان تطبيقك يتطلّب نمطًا مختلفًا للتنقّل للخلف، يمكنك تجاهل هذا السلوك من خلال تحديد خيار BackNavigationBehavior آخر.
BackNavigationBehavior خيار
يستخدم القسم التالي مثالاً لتطبيق بريد إلكتروني يتضمّن قائمة بالرسائل الإلكترونية في جزء واحد وعرضًا مفصّلاً في الجزء الآخر.
PopUntilScaffoldValueChange (الإعداد التلقائي والمُقترَح في معظم الحالات)
يركّز هذا السلوك على التغييرات في بنية التنسيق العام. في إعدادات متعددة اللوحات، لا يؤدي تغيير محتوى البريد الإلكتروني في اللوحة التفصيلية إلى تغيير بنية التنسيق الأساسية. لذلك، قد يؤدي الضغط على زر الرجوع إلى الخروج من التطبيق أو من الرسم البياني الحالي للتنقّل، لأنّه لا يوجد تغيير في التصميم يمكن الرجوع إليه ضمن السياق الحالي. في التصميم ذي اللوحة الواحدة، سيؤدي الضغط على زر الرجوع إلى تخطّي التغييرات في المحتوى ضمن العرض التفصيلي والرجوع إلى عرض القائمة، لأنّ ذلك يمثّل تغييرًا واضحًا في التصميم.
في ما يلي أمثلة:
اللوحات المتعددة: أنت تعرض رسالة إلكترونية (العنصر 1) في لوحة التفاصيل. يؤدي النقر على رسالة إلكترونية أخرى (العنصر 2) إلى تعديل جزء التفاصيل، ولكن يظل جزءا القائمة والتفاصيل مرئيين. قد يؤدي الضغط على زر الرجوع إلى الخروج من التطبيق أو مسار التنقّل الحالي.
اللوحة الفردية: يمكنك عرض العنصر 1، ثم العنصر 2، وسيؤدي الضغط على "رجوع" إلى إرجاعك مباشرةً إلى لوحة قائمة الرسائل الإلكترونية.
استخدِم هذا الخيار عندما تريد أن يلاحظ المستخدمون انتقالات مميّزة في التنسيق مع كل إجراء رجوع.
PopUntilContentChange
يمنح هذا السلوك الأولوية للمحتوى المعروض. إذا عرضت العنصر 1 ثم العنصر 2، سيؤدي الضغط على زر الرجوع إلى عرض العنصر 1، بغض النظر عن التنسيق.
في ما يلي أمثلة:
اللوحات المتعدّدة: يمكنك عرض العنصر 1 في لوحة التفاصيل، ثم النقر على العنصر 2 في القائمة. يتم تعديل جزء التفاصيل. سيؤدي الضغط على زر الرجوع إلى إعادة جزء التفاصيل إلى العنصر 1.
اللوحة الفردية: يحدث رجوع إلى المحتوى نفسه.
استخدِم هذا الخيار عندما يتوقّع المستخدم العودة إلى المحتوى الذي تم عرضه سابقًا من خلال إجراء الرجوع.
PopUntilCurrentDestinationChange
يؤدي هذا السلوك إلى إزالة جميع العناصر من حزمة الخلف إلى أن تتغير وجهة التنقّل الحالية. وينطبق ذلك بالتساوي على التصاميم ذات اللوحة الواحدة والمتعددة اللوحات.
في ما يلي أمثلة:
بغض النظر عمّا إذا كنت تستخدم تخطيطًا أحاديًا أو متعدّد اللوحات، سيؤدي الضغط على زر الرجوع دائمًا إلى نقل التركيز من عنصر التنقّل المحدّد إلى الوجهة السابقة. في تطبيق البريد الإلكتروني، يعني ذلك أنّ المؤشر المرئي للجزء المحدّد سيتغيّر.
استخدِم هذا الخيار عندما يكون الحفاظ على مؤشر مرئي واضح للتنقّل الحالي أمرًا بالغ الأهمية لتجربة المستخدم.
PopLatest
يزيل هذا الخيار الوجهة الأحدث فقط من سجلّ الرجوع. استخدِم هذا الخيار للتنقّل للخلف بدون تخطّي الحالات الوسيطة.
بعد تنفيذ هذه الخطوات، من المفترض أن يبدو الرمز البرمجي مشابهاً لما يلي:
valscaffoldNavigator=rememberListDetailPaneScaffoldNavigator<MyItem>()valscope=rememberCoroutineScope()NavigableListDetailPaneScaffold(navigator=scaffoldNavigator,listPane={AnimatedPane{MyList(onItemClick={item->
// Navigate to the detail pane with the passed itemscope.launch{scaffoldNavigator.navigateTo(ListDetailPaneScaffoldRole.Detail,item)}},)}},detailPane={AnimatedPane{// Show the detail pane content if selected item is availablescaffoldNavigator.currentDestination?.contentKey?.let{MyDetails(it)}}},)
يخضع كل من المحتوى وعيّنات التعليمات البرمجية في هذه الصفحة للتراخيص الموضحّة في ترخيص استخدام المحتوى. إنّ Java وOpenJDK هما علامتان تجاريتان مسجَّلتان لشركة Oracle و/أو الشركات التابعة لها.
تاريخ التعديل الأخير: 2025-08-22 (حسب التوقيت العالمي المتفَّق عليه)
[[["يسهُل فهم المحتوى.","easyToUnderstand","thumb-up"],["ساعَدني المحتوى في حلّ مشكلتي.","solvedMyProblem","thumb-up"],["غير ذلك","otherUp","thumb-up"]],[["لا يحتوي على المعلومات التي أحتاج إليها.","missingTheInformationINeed","thumb-down"],["الخطوات معقدة للغاية / كثيرة جدًا.","tooComplicatedTooManySteps","thumb-down"],["المحتوى قديم.","outOfDate","thumb-down"],["ثمة مشكلة في الترجمة.","translationIssue","thumb-down"],["مشكلة في العيّنات / التعليمات البرمجية","samplesCodeIssue","thumb-down"],["غير ذلك","otherDown","thumb-down"]],["تاريخ التعديل الأخير: 2025-08-22 (حسب التوقيت العالمي المتفَّق عليه)"],[],[],null,["List-detail is a UI pattern that consists of a dual-pane layout where one pane\npresents a list of items and another pane displays the details of items selected\nfrom the list.\n\nThe pattern is particularly useful for applications that provide in-depth\ninformation about elements of large collections, for example, an email client\nthat has a list of emails and the detailed content of each email message.\nList-detail can also be used for less critical paths such as dividing app\npreferences into a list of categories with the preferences for each category in\nthe detail pane.\n**Figure 1.** When enough screen size is available, the detail pane is shown alongside the list pane. **Figure 2.** When screen size is limited, the detail pane (since an item has been selected) takes over the whole space.\n\nImplement the List-Detail Pattern with `NavigableListDetailPaneScaffold`\n\n`NavigableListDetailPaneScaffold` is a composable that simplifies implementing a\nlist-detail layout in Jetpack Compose. It wraps `ListDetailPaneScaffold` and\nadds built-in navigation and predictive back animations.\n\nA list-detail scaffold supports up to three panes:\n\n1. **List pane**: Displays a collection of items.\n2. **Detail pane**: Shows the details of a selected item.\n3. **Extra pane (*optional*)**: Provides additional context when needed.\n\nThe scaffold adapts based on window size:\n\n- In large windows, the list and detail panes appear side by side.\n- In small windows, only one pane is visible at a time, switching as users navigate.\n\nDeclare dependencies\n\n`NavigableListDetailPaneScaffold` is part of the [Material 3 adaptive navigation\nlibrary](/reference/kotlin/androidx/compose/material3/adaptive/layout/package-summary).\n\nAdd the following three related dependencies to the `build.gradle` file of your\napp or module: \n\nKotlin \n\n```kotlin\nimplementation(\"androidx.compose.material3.adaptive:adaptive\")\nimplementation(\"androidx.compose.material3.adaptive:adaptive-layout\")\nimplementation(\"androidx.compose.material3.adaptive:adaptive-navigation\")\n```\n\nGroovy \n\n```groovy\nimplementation 'androidx.compose.material3.adaptive:adaptive'\nimplementation 'androidx.compose.material3.adaptive:adaptive-layout'\nimplementation 'androidx.compose.material3.adaptive:adaptive-navigation'\n```\n\n- adaptive: Low-level building blocks such as [`HingeInfo`](/reference/kotlin/androidx/compose/material3/adaptive/HingeInfo) and [`Posture`](/reference/kotlin/androidx/compose/material3/adaptive/Posture)\n- adaptive-layout: Adaptive layouts such as `ListDetailPaneScaffold` and [`SupportingPaneScaffold`](/reference/kotlin/androidx/compose/material3/adaptive/layout/package-summary#SupportingPaneScaffold(androidx.compose.material3.adaptive.layout.PaneScaffoldDirective,androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue,kotlin.Function1,kotlin.Function1,androidx.compose.ui.Modifier,kotlin.Function1))\n- adaptive-navigation: Composables for navigating within and between panes, as well as adaptive layouts that support navigation by default such as `NavigableListDetailPaneScaffold` and `NavigableSupportingPaneScaffold`\n\nEnsure your project includes [compose-material3-adaptive version 1.1.0-beta1](/jetpack/androidx/releases/compose-material3-adaptive#1.1.0-beta01)\nor higher.\n\nOpt-in to the predictive back gesture\n\nTo enable predictive back animations in Android 15 or lower, you must opt-in\nto support the predictive back gesture. To opt-in, add\n`android:enableOnBackInvokedCallback=\"true\"` to the `\u003capplication\u003e` tag or\nindividual `\u003cactivity\u003e` tags within your `AndroidManifest.xml` file. For more\ninformation, see [Opt-in to the predictive back gesture](/guide/navigation/custom-back/predictive-back-gesture#opt-predictive).\n\nOnce your app targets Android 16 (API level 36) or higher, predictive back is\nenabled by default.\n\nBasic usage\n\nImplement `NavigableListDetailPaneScaffold` as follows:\n\n1. Use a class that represents the selected content. Use a [`Parcelable`](/reference/android/os/Parcelable) class to support saving and restoring the selected list item. Use the [kotlin-parcelize plugin](/kotlin/parcelize) to generate the code for you.\n2. Create a `ThreePaneScaffoldNavigator` with `rememberListDetailPaneScaffoldNavigator`.\n\nThis navigator is used to move between the list, detail, and extra panes. By\ndeclaring a generic type, the navigator also tracks the state of the scaffold\n(that is, which `MyItem` is being displayed). Since this type is parcelable, the\nstate can be saved and restored by the navigator to automatically handle\nconfiguration changes.\n\n1. Pass the navigator to the `NavigableListDetailPaneScaffold` composable.\n\n2. Supply your list pane implementation to the\n `NavigableListDetailPaneScaffold`. Use [`AnimatedPane`](/reference/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldScope#(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope).AnimatedPane(androidx.compose.ui.Modifier,kotlin.Function1)) to apply the\n default pane animations during navigation. Then use `ThreePaneScaffoldNavigator`\n to navigate to the detail pane, `ListDetailPaneScaffoldRole.Detail`, and display\n the passed item.\n\n3. Include your detail pane implementation in `NavigableListDetailPaneScaffold`.\n\nWhen navigation is complete, `currentDestination` contains the pane your app\nhas navigated to, including the content displayed in the pane. The `contentKey`\nproperty is the same type specified in the original call so you can access\nany data that you need to display.\n\n1. Optionally, change the `defaultBackBehavior` in `NavigableListDetailPaneScaffold`. By default, `NavigableListDetailPaneScaffold` uses `PopUntilScaffoldValueChange` for `defaultBackBehavior`.\n\nIf your app requires a different back navigation pattern, you can override this\nbehavior by specifying another `BackNavigationBehavior` option.\n\n`BackNavigationBehavior` options\n\nThe following section uses the example of an email app with a list of emails in\none pane and a detailed view in the other.\n\n`PopUntilScaffoldValueChange` (Default and recommended in most cases)\n\nThis behavior focuses on changes to the overall layout structure. In a\nmulti-pane setup, changing the email content in the detailed pane doesn't alter\nthe underlying layout structure. Therefore, the back button might exit the app\nor the current navigation graph because there's no layout change to revert to\nwithin the current context. In a single-pane layout, pressing back will skip\nthrough content changes within the detail view and return to the list view, as\nthis represents a clear layout change.\n\nConsider the following examples:\n\n- **Multi-Pane:** You're viewing an email (Item 1) in the detail pane. Clicking on another email (Item 2) updates the detail pane, but the list and detail panes remain visible. Pressing back might exit the app or the current navigation flow.\n- **Single-Pane:** You view Item 1, then Item 2, pressing back will return you directly to the email list pane.\n\nUse this when you want users to perceive distinct layout transitions with each\nback action.\n\n`PopUntilContentChange`\n\nThis behavior prioritizes the content displayed. If you view Item 1 and then\nItem 2, pressing back will revert to Item 1, regardless of the layout.\n\nConsider the following examples:\n\n- **Multi-Pane:** You view Item 1 in the detail pane, then click Item 2 in the list. The detail pane updates. Pressing back will restore the detail pane to Item 1.\n- **Single-Pane:** The same content reversion occurs.\n\nUse this when your user expects to return to the previously viewed content with\nthe back action.\n\n`PopUntilCurrentDestinationChange`\n\nThis behavior pops the back stack until the *current navigation destination*\nchanges. This applies equally to single and multi-pane layouts.\n\nConsider the following examples:\n\nRegardless of whether you're in a single or multi-pane layout, pressing back\nwill always move the focus from the highlighted navigation element to the\nprevious destination. In our email app, this means the visual indication of\nthe selected pane will shift.\n\nUse this when maintaining a clear visual indication of the current navigation\nis crucial for the user experience.\n\n`PopLatest`\n\nThis option removes only the most recent destination from the backstack. Use\nthis option for back navigation without skipping intermediate states.\n| **Note:** Multi-pane layouts may create navigation backstacks that are not possible in single-pane layouts, such as navigating directly from one detail item to another. If the device size changes mid-navigation, this behavior may produce unintuitive results.\n\nAfter you implement these steps, your code should look similar to the following:\n\n\n```kotlin\nval scaffoldNavigator = rememberListDetailPaneScaffoldNavigator\u003cMyItem\u003e()\nval scope = rememberCoroutineScope()\n\nNavigableListDetailPaneScaffold(\n navigator = scaffoldNavigator,\n listPane = {\n AnimatedPane {\n MyList(\n onItemClick = { item -\u003e\n // Navigate to the detail pane with the passed item\n scope.launch {\n scaffoldNavigator.navigateTo(\n ListDetailPaneScaffoldRole.Detail,\n item\n )\n }\n },\n )\n }\n },\n detailPane = {\n AnimatedPane {\n // Show the detail pane content if selected item is available\n scaffoldNavigator.currentDestination?.contentKey?.let {\n MyDetails(it)\n }\n }\n },\n)https://github.com/android/snippets/blob/5673ffc60b614daf028ee936227128eb8c4f9781/compose/snippets/src/main/java/com/example/compose/snippets/adaptivelayouts/SampleListDetailPaneScaffold.kt#L119-L147\n```\n\n\u003cbr /\u003e"]]