בניית פריסה של רשימה ופירוט

רשימה-פרטים היא תבנית של ממשק המשתמש שמורכבת מפריסה של שתי חלוניות, שבה חלונית אחת מציגה רשימה של פריטים, וחלונית אחרת מציגה את פרטי הפריטים שנבחרו מהרשימה.

התבנית מועילה במיוחד לאפליקציות שמספקות מידע מעמיק על רכיבים של אוספים גדולים. לדוגמה, לקוח אימייל עם רשימת אימיילים והתוכן המפורט של כל הודעת אימייל. אפשר להשתמש בחלונית 'רשימת פרטים' גם בנתיבים פחות קריטיים, כמו חלוקת ההעדפות של האפליקציה לרשימת קטגוריות, כאשר ההעדפות של כל קטגוריה מוצגות בחלונית הפרטים.

הטמעה של דפוס ממשק משתמש עם ListDetailPaneScaffold

ListDetailPaneScaffold הוא רכיב שאפשר לשלב כדי לפשט את ההטמעה של תבנית הרשימה-פרטים באפליקציה. תבנית הרשימה-פרטים יכולה להכיל עד שלוש חלוניות: חלונית רשימה, חלונית פרטים וחלונית נוספת אופציונלית. בסכימה הזו, ה-scaffold מטפל בחישובים של שטח המסך. כשיש מספיק מקום במסך, חלונית הפרטים מוצגת לצד חלונית הרשימה. במסכים קטנים, מערך הנתונים עובר באופן אוטומטי להצגת מסך מלא של הרשימה או של חלונית הפרטים.

חלונית פרטים שמוצגת לצד דף הרשימה.
איור 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")

Groovy

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)
            }
        }
    },
)