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

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

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

تنفيذ نمط واجهة المستخدم باستخدام ListDetailPaneScaffold

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

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

الإفصاح عن التبعيات

ListDetailPaneScaffold هو جزء من مكتبة التنسيق التكيُّفي 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
  • adaptive-navigation: عناصر قابلة للتجميع للتنقّل داخل اللوحة وبين اللوحات

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

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

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

    @Parcelize
    class MyItem(val id: Int) : Parcelable

  2. أنشئ ThreePaneScaffoldNavigator باستخدام rememberListDetailPaneScaffoldNavigator وأضِف BackHandler. يُستخدَم هذا المخطّط للتنقّل بين اللوحة الرئيسية واللوحة التفصيلية واللوحات الإضافية. من خلال تحديد نوع عام، يتتبّع المتصفّح أيضًا حالة الهيكل العظمي (أي MyItem الذي يتم عرضه). بما أنّ هذا النوع قابل للتقسيم، يمكن للمستكشف حفظ الحالة واستعادتها لمعالجة التغييرات في الإعدادات تلقائيًا. يتيح الرمز BackHandler الرجوع باستخدام إيماءة الرجوع في النظام أو الزر. يعتمد السلوك المتوقّع لزر الرجوع في ListDetailPaneScaffold على حجم النافذة وقيمة الإطار الحالي. إذا كان ListDetailPaneScaffold يتيح الرجوع إلى الحالة الحالية، يكون canNavigateBack() هو true، ما يتيح استخدام BackHandler.

    val navigator = rememberListDetailPaneScaffoldNavigator<MyItem>()
    
    BackHandler(navigator.canNavigateBack()) {
        navigator.navigateBack()
    }

  3. انقل scaffoldState من navigator إلى العنصر القابل للتجميع ListDetailPaneScaffold.

    ListDetailPaneScaffold(
        directive = navigator.scaffoldDirective,
        value = navigator.scaffoldValue,
        // ...
    )

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

    ListDetailPaneScaffold(
        directive = navigator.scaffoldDirective,
        value = navigator.scaffoldValue,
        listPane = {
            AnimatedPane {
                MyList(
                    onItemClick = { item ->
                        // Navigate to the detail pane with the passed item
                        navigator.navigateTo(ListDetailPaneScaffoldRole.Detail, item)
                    }
                )
            }
        },
        // ...
    )

  5. أدرِج عملية تنفيذ اللوحة التفصيلية في ListDetailPaneScaffold. عند اكتمال التنقّل، يحتوي currentDestination على اللوحة التي انتقّل إليها تطبيقك، بما في ذلك المحتوى المعروض في اللوحة. سمة content هي من النوع نفسه المحدّد في طلب التذكر الأصلي (MyItem في هذا المثال)، لذا يمكنك أيضًا الوصول إلى السمة لأي بيانات تحتاج إلى عرضها.

    ListDetailPaneScaffold(
        directive = navigator.scaffoldDirective,
        value = navigator.scaffoldValue,
        listPane =
        // ...
        detailPane = {
            AnimatedPane {
                navigator.currentDestination?.content?.let {
                    MyDetails(it)
                }
            }
        },
    )

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

val navigator = rememberListDetailPaneScaffoldNavigator<MyItem>()

BackHandler(navigator.canNavigateBack()) {
    navigator.navigateBack()
}

ListDetailPaneScaffold(
    directive = navigator.scaffoldDirective,
    value = navigator.scaffoldValue,
    listPane = {
        AnimatedPane {
            MyList(
                onItemClick = { item ->
                    // Navigate to the detail pane with the passed item
                    navigator.navigateTo(ListDetailPaneScaffoldRole.Detail, item)
                },
            )
        }
    },
    detailPane = {
        AnimatedPane {
            // Show the detail pane content if selected item is available
            navigator.currentDestination?.content?.let {
                MyDetails(it)
            }
        }
    },
)