העברת CoordinatorLayout לכתיבה

CoordinatorLayout הוא ViewGroup שמאפשר פריסות מורכבות, חופפות ומקוננות. הוא משמש כמאגר כדי להפעיל אינטראקציות ספציפיות של Material Design, כמו הרחבה או כיווץ של סרגלי כלים וגיליונות תחתונים, עבור תצוגות שמוכלות בו.

במצב כתיבה, האקווילנט הקרוב ביותר ל-CoordinatorLayout הוא Scaffold. Scaffold מספק משבצות תוכן לשילוב של רכיבי Material בדפוסי מסך ובאינטראקציות נפוצים. בדף הזה מוסבר איך אפשר להעביר את ההטמעה של CoordinatorLayout לשימוש ב-Scaffold ב-Compose.

שלבים בהעברה

כדי להעביר את CoordinatorLayout אל Scaffold, צריך לבצע את השלבים הבאים:

  1. בדוגמה הבאה, התג CoordinatorLayout מכיל את התג AppBarLayout שכולל את התג ToolBar, התג ViewPager והתג FloatingActionButton. מוסיפים הערה ל-CoordinatorLayout ולרכיבי הצאצא שלו בהיררכיית ממשק המשתמש, ומוסיפים ComposeView במקומו.

    <!--  <androidx.coordinatorlayout.widget.CoordinatorLayout-->
    <!--      android:id="@+id/coordinator_layout"-->
    <!--      android:layout_width="match_parent"-->
    <!--      android:layout_height="match_parent"-->
    <!--      android:fitsSystemWindows="true">-->
    
    <!--    <androidx.compose.ui.platform.ComposeView-->
    <!--        android:id="@+id/compose_view"-->
    <!--        android:layout_width="match_parent"-->
    <!--        android:layout_height="match_parent"-->
    <!--        app:layout_behavior="@string/appbar_scrolling_view_behavior" />-->
    
    <!--    <com.google.android.material.appbar.AppBarLayout-->
    <!--        android:id="@+id/app_bar_layout"-->
    <!--        android:layout_width="match_parent"-->
    <!--        android:layout_height="wrap_content"-->
    <!--        android:fitsSystemWindows="true"-->
    <!--        android:theme="@style/Theme.Sunflower.AppBarOverlay">-->
    
        <!-- AppBarLayout contents here -->
    
    <!--    </com.google.android.material.appbar.AppBarLayout>-->
    
    <!--  </androidx.coordinatorlayout.widget.CoordinatorLayout>-->
    
    <androidx.compose.ui.platform.ComposeView
        android:id="@+id/compose_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    
  2. ב-Fragment או ב-Activity, מקבלים הפניה אל ComposeView שהוספתם זה עתה ומפעילים את השיטה setContent. בגוף השיטה, מגדירים את Scaffold כתוכן שלה:

    composeView.setContent {
        Scaffold(Modifier.fillMaxSize()) { contentPadding ->
            // Scaffold contents
            // ...
        }
    }

  3. בתוכן של Scaffold, מוסיפים את התוכן הראשי של המסך. התוכן העיקרי בקובץ ה-XML שלמעלה הוא ViewPager2, ולכן נשתמש ב-HorizontalPager, שהוא המקבילה של ViewPager2 ב-Compose. ה-content lambda של Scaffold מקבל גם מופע של PaddingValues שצריך להחיל על שורש התוכן. אפשר להשתמש ב-Modifier.padding כדי להחיל את אותו PaddingValues על HorizontalPager.

    composeView.setContent {
        Scaffold(Modifier.fillMaxSize()) { contentPadding ->
            val pagerState = rememberPagerState {
                10
            }
            HorizontalPager(
                state = pagerState,
                modifier = Modifier.padding(contentPadding)
            ) { /* Page contents */ }
        }
    }

  4. אפשר להשתמש במשבצות תוכן אחרות ש-Scaffold מספק כדי להוסיף עוד רכיבים למסך ולהעביר את שאר ה-Views של הילדים. אפשר להשתמש במשבצת topBar כדי להוסיף TopAppBar, ובמשבצת floatingActionButton כדי לספק FloatingActionButton.

    composeView.setContent {
        Scaffold(
            Modifier.fillMaxSize(),
            topBar = {
                TopAppBar(
                    title = {
                        Text("My App")
                    }
                )
            },
            floatingActionButton = {
                FloatingActionButton(
                    onClick = { /* Handle click */ }
                ) {
                    Icon(
                        Icons.Filled.Add,
                        contentDescription = "Add Button"
                    )
                }
            }
        ) { contentPadding ->
            val pagerState = rememberPagerState {
                10
            }
            HorizontalPager(
                state = pagerState,
                modifier = Modifier.padding(contentPadding)
            ) { /* Page contents */ }
        }
    }

תרחישים נפוצים לדוגמה

כיווץ והרחבה של סרגלי כלים

בתצוגת המערכת, כדי לכווץ ולהרחיב את סרגל הכלים עם CoordinatorLayout, משתמשים ב-AppBarLayout כמאגר לסרגל הכלים. אחר כך תוכלו לציין Behavior דרך layout_behavior ב-XML בתצוגה המשויכת שאפשר לגלול בה (כמו RecyclerView או NestedScrollView) כדי להצהיר איך סרגל הכלים מתכווץ או מתרחב כשגוללים.

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

  1. ניתן להתקשר אל TopAppBarDefaults.enterAlwaysScrollBehavior() כדי ליצור TopAppBarScrollBehavior.
  2. מספקים את TopAppBarScrollBehavior שנוצר לTopAppBar.
  3. מקשרים את NestedScrollConnection דרך Modifier.nestedScroll ב-Scaffold כדי שה-Scaffold יוכל לקבל אירועי גלילה מקוננים כשהתוכן שאפשר לגלול בו עולה או יורד. כך, סרגל האפליקציות שמוכל בתוך המסך יכול להצטמצם או להתרחב בהתאם לגלילה של התוכן.

    // 1. Create the TopAppBarScrollBehavior
    val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()
    
    Scaffold(
        topBar = {
            TopAppBar(
                title = {
                    Text("My App")
                },
                // 2. Provide scrollBehavior to TopAppBar
                scrollBehavior = scrollBehavior
            )
        },
        // 3. Connect the scrollBehavior.nestedScrollConnection to the Scaffold
        modifier = Modifier
            .fillMaxSize()
            .nestedScroll(scrollBehavior.nestedScrollConnection)
    ) { contentPadding ->
        /* Contents */
        // ...
    }

התאמה אישית של אפקט הגלילה של כיווץ והרחבה

אפשר לספק כמה פרמטרים ל-enterAlwaysScrollBehavior כדי להתאים אישית את אפקט האנימציה של הכיווץ וההרחבה. ‫TopAppBarDefaults מספק גם TopAppBarScrollBehavior אחרים, כמו exitUntilCollapsedScrollBehavior, שמרחיב את סרגל האפליקציות רק כשגוללים את התוכן עד למטה.

כדי ליצור אפקט בהתאמה אישית מלאה (לדוגמה, אפקט פרלקסה), אפשר גם ליצור NestedScrollConnection משלכם ולהזיז את סרגל הכלים באופן ידני בזמן שהתוכן נגלל. דוגמת קוד מופיעה בדוגמה של גלילה מקוננת ב-AOSP.

מגירות

ב-Views, מטמיעים חלונית ניווט באמצעות DrawerLayout כתצוגת הבסיס. בתמורה, התצוגה CoordinatorLayout היא תצוגת צאצא של התצוגה DrawerLayout. ה-DrawerLayout מכיל גם תצוגת צאצא אחרת, כמו NavigationView, כדי להציג את אפשרויות הניווט במגירה.

ב-Compose, אפשר להטמיע מגירת ניווט באמצעות הקומפוזבל ModalNavigationDrawer. ב-ModalNavigationDrawer יש חריץ drawerContent למגירה וחריץ content לתוכן המסך.

ModalNavigationDrawer(
    drawerContent = {
        ModalDrawerSheet {
            Text("Drawer title", modifier = Modifier.padding(16.dp))
            HorizontalDivider()
            NavigationDrawerItem(
                label = { Text(text = "Drawer Item") },
                selected = false,
                onClick = { /*TODO*/ }
            )
            // ...other drawer items
        }
    }
) {
    Scaffold(Modifier.fillMaxSize()) { contentPadding ->
        // Scaffold content
        // ...
    }
}

מידע נוסף זמין במאמר בנושא חלוניות.

סרגלים אינטראקטיביים

Scaffold מספק חריץ snackbarHost שיכול לקבל SnackbarHost composable כדי להציג Snackbar.

val scope = rememberCoroutineScope()
val snackbarHostState = remember { SnackbarHostState() }
Scaffold(
    snackbarHost = {
        SnackbarHost(hostState = snackbarHostState)
    },
    floatingActionButton = {
        ExtendedFloatingActionButton(
            text = { Text("Show snackbar") },
            icon = { Icon(Icons.Filled.Image, contentDescription = "") },
            onClick = {
                scope.launch {
                    snackbarHostState.showSnackbar("Snackbar")
                }
            }
        )
    }
) { contentPadding ->
    // Screen content
    // ...
}

מידע נוסף זמין במאמר בנושא הודעות סנאקבר.

מידע נוסף

מידע נוסף על העברת CoordinatorLayout ל-Compose זמין במקורות המידע הבאים: