פיתוח ניווט דינמי

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

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

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

הוספת יחסי תלות

NavigationSuiteScaffold הוא חלק מ חבילת ניווט מותאם של Material3 לספרייה. יש להוסיף תלות לספרייה בקובץ build.gradle של האפליקציה או מודול:

Kotlin


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

מגניב


implementation 'androidx.compose.material3:material3-adaptive-navigation-suite'

יצירת פיסול

שני החלקים העיקריים של NavigationSuiteScaffold הם הפריטים של חבילת הניווט והתוכן עבור היעד שנבחר. אפשר להגדיר ישירות בתוכן קומפוזבילי עם פריטי ניווט, אבל מקובל להגדיר במקום אחר, למשל ב-enum:

enum class AppDestinations(
    @StringRes val label: Int,
    val icon: ImageVector,
    @StringRes val contentDescription: Int
) {
    HOME(R.string.home, Icons.Default.Home, R.string.home),
    FAVORITES(R.string.favorites, Icons.Default.Favorite, R.string.favorites),
    SHOPPING(R.string.shopping, Icons.Default.ShoppingCart, R.string.shopping),
    PROFILE(R.string.profile, Icons.Default.AccountBox, R.string.profile),
}

כדי להשתמש בNavigationSuiteScaffold, צריך לעקוב אחר היעד הנוכחי, אפשר לעשות באמצעות rememberSaveable:

var currentDestination by rememberSaveable { mutableStateOf(AppDestinations.HOME) }

בדוגמה הבאה, הפרמטר navigationSuiteItems (סוג NavigationSuiteScope משתמש בפונקציה item כדי להגדיר את ממשק המשתמש של הניווט ליעד ספציפי. ממשק המשתמש של היעד בשימוש בין סרגלי ניווט, מסילות וחלונית הזזה. כדי ליצור פריטי ניווט, צריך בלופ AppDestinations (מוגדר בקטע הקוד הקודם):

NavigationSuiteScaffold(
    navigationSuiteItems = {
        AppDestinations.entries.forEach {
            item(
                icon = {
                    Icon(
                        it.icon,
                        contentDescription = stringResource(it.contentDescription)
                    )
                },
                label = { Text(stringResource(it.label)) },
                selected = it == currentDestination,
                onClick = { currentDestination = it }
            )
        }
    }
) {
    // TODO: Destination content.
}

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

NavigationSuiteScaffold(
    navigationSuiteItems = { /*...*/ }
) {
    // Destination content.
    when (currentDestination) {
        AppDestinations.HOME -> HomeDestination()
        AppDestinations.FAVORITES -> FavoritesDestination()
        AppDestinations.SHOPPING -> ShoppingDestination()
        AppDestinations.PROFILE -> ProfileDestination()
    }
}

שינוי צבעים

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

הפרמטר containerColor מציין את צבע המשטח. ברירת המחדל הוא צבע הרקע של ערכת הצבעים שלכם. הפרמטר contentColor מציין את הצבע של התוכן באתר שמופיע. ברירת המחדל היא 'מופעל'. צבע של containerColor שצוין. לדוגמה, אם containerColor משתמש בצבע background, ואז contentColor משתמש בצבע onBackground. אפשר לעיין בנושא Material Design 3 ב'כתיבה' לקבלת פרטים נוספים על אופן הפעולה של מערכת הצבעים. כשמשנים את הערכים האלה, צריך להשתמש בערכים שהוגדרו בעיצוב כדי שהאפליקציה תתמוך בתצוגה כהה או בהירה מצבים:

NavigationSuiteScaffold(
    navigationSuiteItems = { /* ... */ },
    containerColor = MaterialTheme.colorScheme.primary,
    contentColor = MaterialTheme.colorScheme.onPrimary,
) {
    // Content...
}

ממשק המשתמש של הניווט מוצג לפני השטח של NavigationSuiteScaffold. ערכי ברירת המחדל של צבעי ממשק המשתמש נקבעים לפי NavigationSuiteDefaults.colors(), אבל לא גם יכולים לשנות את הערכים האלה. לדוגמה, אם רוצים שהרקע של שסרגל הניווט יהיה שקוף, אבל שאר הערכים יהיו ברירות המחדל, לשנות את navigationBarContainerColor:

NavigationSuiteScaffold(
    navigationSuiteItems = { /* ... */ },
    navigationSuiteColors = NavigationSuiteDefaults.colors(
        navigationBarContainerColor = Color.Transparent,
    )
) {
    // Content...
}

בסופו של דבר, אפשר להתאים אישית כל פריט בממשק המשתמש של הניווט. כשמפעילים את את הפונקציה item, אפשר להעביר במופע של NavigationSuiteItemColors הכיתה מציינת הצבעים של הפריטים בסרגל הניווט, ברכבת הניווט ובניווט חלונית הזזה. כלומר, יכולים להיות צבעים זהים בכל סוג של ממשק המשתמש לניווט, או שאפשר לשנות את הצבעים בהתאם לצרכים שלכם. להגדיר את הצבעים רמת NavigationSuiteScaffold לשימוש באותו מופע אובייקט בכל הפריטים וקריאה לפונקציה NavigationSuiteDefaults.itemColors() כדי לשנות רק את ההגדרה אלו שברצונך לשנות:

val myNavigationSuiteItemColors = NavigationSuiteDefaults.itemColors(
    navigationBarItemColors = NavigationBarItemDefaults.colors(
        indicatorColor = MaterialTheme.colorScheme.primaryContainer,
        selectedIconColor = MaterialTheme.colorScheme.onPrimaryContainer
    ),
)

NavigationSuiteScaffold(
    navigationSuiteItems = {
        AppDestinations.entries.forEach {
            item(
                icon = {
                    Icon(
                        it.icon,
                        contentDescription = stringResource(it.contentDescription)
                    )
                },
                label = { Text(stringResource(it.label)) },
                selected = it == currentDestination,
                onClick = { currentDestination = it },
                colors = myNavigationSuiteItemColors,
            )
        }
    },
) {
    // Content...
}

התאמה אישית של סוגי הניווט

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

val adaptiveInfo = currentWindowAdaptiveInfo()
val customNavSuiteType = with(adaptiveInfo) {
    if (windowSizeClass.windowWidthSizeClass == WindowWidthSizeClass.EXPANDED) {
        NavigationSuiteType.NavigationDrawer
    } else {
        NavigationSuiteScaffoldDefaults.calculateFromAdaptiveInfo(adaptiveInfo)
    }
}

NavigationSuiteScaffold(
    navigationSuiteItems = { /* ... */ },
    layoutType = customNavSuiteType,
) {
    // Content...
}

מקורות מידע נוספים

יש לעיין בהנחיות לגבי Material Design:

אפשר לעיין ברכיבים הבאים של ספריית androidx.compose.material3: