פריסת החלונית התומכת מאפשרת למשתמש להתמקד בתוכן העיקרי של האפליקציה, תוך הצגת מידע תומך רלוונטי. לדוגמה, בחלונית הראשית יכולים להופיע פרטים על סרט, ובחלונית המשנית יכולים להופיע סרטים דומים, סרטים של אותו במאי או סרטים עם אותם שחקנים.
פרטים נוספים זמינים בהנחיות לגבי חלונית תומכת של Material 3.
הטמעה של חלונית תמיכה באמצעות scaffold
NavigableSupportingPaneScaffold הוא קומפוזבילי שמפשט את ההטמעה של פריסת חלונית תומכת ב-Jetpack פיתוח נייטיב. היא עוטפת את SupportingPaneScaffold ומוסיפה ניווט מובנה וטיפול חיזוי בהחזרה.
פיגום של חלונית תומכת יכול להכיל עד שלוש חלוניות:
- החלונית הראשית: מוצג בה התוכן העיקרי.
- חלונית תומכת: מספקת הקשר נוסף או כלים שקשורים לחלונית הראשית.
- חלונית נוספת (אופציונלית): משמשת לתוכן משלים כשצריך.
הפיגום מותאם בהתאם לגודל החלון:
- בחלונות גדולים, החלוניות הראשיות והמשניות מופיעות זו לצד זו.
בחלונות קטנים, רק חלונית אחת מוצגת בכל פעם, והן מתחלפות כשהמשתמשים עוברים בין האפשרויות.
איור 1. תמיכה בפריסת חלוניות.
הוספת יחסי תלות
NavigableSupportingPaneScaffold הוא חלק מספריית הפריסות המותאמות של 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'
adaptive-layout: פריסות מותאמות כמו
ListDetailPaneScaffoldו-SupportingPaneScaffoldadaptive-navigation: קומפוזבלים לניווט בתוך חלוניות וביניהן, ופריסות מותאמות שתומכות בניווט כברירת מחדל, כמו
NavigableListDetailPaneScaffoldו-NavigableSupportingPaneScaffold
מוודאים שהפרויקט כולל את compose-material3-adaptive גרסה 1.1.0-beta1 ואילך.
הצטרפות לשימוש בחיזוי תנועת החזרה
כדי להפעיל אנימציות של חיזוי החזרה ב-Android 15 ומטה, צריך להביע הסכמה לתמיכה בתנועת חיזוי החזרה. כדי להפעיל את ההגדרה, מוסיפים את המחרוזת
android:enableOnBackInvokedCallback="true" לתג <application> או לתגי <activity> בודדים בקובץ AndroidManifest.xml.
אחרי שהאפליקציה מטרגטת ל-Android 16 (רמת API 36) ומעלה, התכונה 'חזרה עם תצוגה מקדימה' מופעלת כברירת מחדל.
יצירת כלי ניווט
בחלונות קטנים, מוצג רק חלונית אחת בכל פעם, לכן צריך להשתמש בThreePaneScaffoldNavigator כדי לעבור בין החלוניות. יוצרים מופע של ה-Navigator באמצעות rememberSupportingPaneScaffoldNavigator.
val scaffoldNavigator = rememberSupportingPaneScaffoldNavigator() val scope = rememberCoroutineScope()
מעבירים את ה-navigator ל-scaffold
ה-scaffold דורש ThreePaneScaffoldNavigator, שהוא ממשק שמייצג את המצב של ה-scaffold, את ThreePaneScaffoldValue ואת PaneScaffoldDirective.
NavigableSupportingPaneScaffold( navigator = scaffoldNavigator, mainPane = { /*...*/ }, supportingPane = { /*...*/ }, )
החלונית הראשית והחלונית המשנית הן רכיבים שאפשר להוסיף להם תוכן. כדי להחיל את אנימציות ברירת המחדל של החלונית במהלך הניווט, משתמשים ב-AnimatedPane. משתמשים בערך של scaffold כדי לבדוק אם חלונית התמיכה מוסתרת. אם כן, מוצג לחצן שקורא ל-navigateTo(SupportingPaneScaffoldRole.Supporting) כדי להציג את חלונית התמיכה.
במסכים גדולים, משתמשים בשיטה ThreePaneScaffoldNavigator.navigateBack() כדי לסגור את החלונית התומכת, ומעבירים את הקבוע BackNavigationBehavior.PopUntilScaffoldValueChange. הפעלת ה-method הזו גורמת לקומפוזיציה מחדש של NavigableSupportingPaneScaffold.
במהלך ההרכבה מחדש, בודקים את המאפיין ThreePaneScaffoldNavigator.currentDestination כדי לקבוע אם להציג את חלונית התמיכה.
הנה הטמעה מלאה של ה-scaffold:
val scaffoldNavigator = rememberSupportingPaneScaffoldNavigator() val scope = rememberCoroutineScope() val backNavigationBehavior = BackNavigationBehavior.PopUntilScaffoldValueChange NavigableSupportingPaneScaffold( navigator = scaffoldNavigator, mainPane = { AnimatedPane( modifier = Modifier .safeContentPadding() .background(Color.Red) ) { if (scaffoldNavigator.scaffoldValue[SupportingPaneScaffoldRole.Supporting] == PaneAdaptedValue.Hidden) { Button( modifier = Modifier .wrapContentSize(), onClick = { scope.launch { scaffoldNavigator.navigateTo(SupportingPaneScaffoldRole.Supporting) } } ) { Text("Show supporting pane") } } else { Text("Supporting pane is shown") } } }, supportingPane = { AnimatedPane(modifier = Modifier.safeContentPadding()) { Column { // Allow users to dismiss the supporting pane. Use back navigation to // hide an expanded supporting pane. if (scaffoldNavigator.scaffoldValue[SupportingPaneScaffoldRole.Supporting] == PaneAdaptedValue.Expanded) { // Material design principles promote the usage of a right-aligned // close (X) button. IconButton( modifier = Modifier.align(Alignment.End).padding(16.dp), onClick = { scope.launch { scaffoldNavigator.navigateBack(backNavigationBehavior) } } ) { Icon(Icons.Default.Close, contentDescription = "Close") } } Text("Supporting pane") } } } )
חילוץ קומפוזיציות של חלוניות
כדי שאפשר יהיה להשתמש בחלוניות נפרדות של SupportingPaneScaffold שוב ולבדוק אותן, צריך לחלץ אותן לרכיבים הניתנים להרכבה משלהן. אם רוצים להשתמש באנימציות שמוגדרות כברירת מחדל, אפשר להשתמש ב-ThreePaneScaffoldScope כדי לגשת ל-AnimatedPane:
@OptIn(ExperimentalMaterial3AdaptiveApi::class) @Composable fun ThreePaneScaffoldPaneScope.MainPane( shouldShowSupportingPaneButton: Boolean, onNavigateToSupportingPane: () -> Unit, modifier: Modifier = Modifier, ) { AnimatedPane( modifier = modifier.safeContentPadding() ) { // Main pane content if (shouldShowSupportingPaneButton) { Button(onClick = onNavigateToSupportingPane) { Text("Show supporting pane") } } else { Text("Supporting pane is shown") } } } @OptIn(ExperimentalMaterial3AdaptiveApi::class) @Composable fun ThreePaneScaffoldPaneScope.SupportingPane( scaffoldNavigator: ThreePaneScaffoldNavigator<Any>, modifier: Modifier = Modifier, backNavigationBehavior: BackNavigationBehavior = BackNavigationBehavior.PopUntilScaffoldValueChange, ) { val scope = rememberCoroutineScope() AnimatedPane(modifier = Modifier.safeContentPadding()) { Column { // Allow users to dismiss the supporting pane. Use back navigation to // hide an expanded supporting pane. if (scaffoldNavigator.scaffoldValue[SupportingPaneScaffoldRole.Supporting] == PaneAdaptedValue.Expanded) { // Material design principles promote the usage of a right-aligned // close (X) button. IconButton( modifier = modifier.align(Alignment.End).padding(16.dp), onClick = { scope.launch { scaffoldNavigator.navigateBack(backNavigationBehavior) } } ) { Icon(Icons.Default.Close, contentDescription = "Close") } } Text("Supporting pane") } } }
הוצאת החלוניות לרכיבים שניתנים להרכבה מפשטת את השימוש ב-SupportingPaneScaffold (אפשר להשוות את הקוד הבא להטמעה המלאה של ה-scaffold בקטע הקודם):
val scaffoldNavigator = rememberSupportingPaneScaffoldNavigator() val scope = rememberCoroutineScope() NavigableSupportingPaneScaffold( navigator = scaffoldNavigator, mainPane = { MainPane( shouldShowSupportingPaneButton = scaffoldNavigator.scaffoldValue.secondary == PaneAdaptedValue.Hidden, onNavigateToSupportingPane = { scope.launch { scaffoldNavigator.navigateTo(ThreePaneScaffoldRole.Secondary) } } ) }, supportingPane = { SupportingPane(scaffoldNavigator = scaffoldNavigator) }, )
אם אתם צריכים יותר שליטה בהיבטים ספציפיים של ה-scaffold, כדאי להשתמש ב-SupportingPaneScaffold במקום ב-NavigableSupportingPaneScaffold. המאפיין הזה מקבל בנפרד את הערכים PaneScaffoldDirective ו-ThreePaneScaffoldValue או ThreePaneScaffoldState. הגמישות הזו מאפשרת לכם להטמיע לוגיקה מותאמת אישית לריווח בין החלוניות ולקבוע כמה חלוניות יוצגו בו-זמנית. אפשר גם להוסיף את ThreePaneScaffoldPredictiveBackHandler כדי להפעיל תמיכה בתכונה 'חזרה עם תצוגה מקדימה'.
הוספה של ThreePaneScaffoldPredictiveBackHandler
מצרפים את handler של חיזוי תנועת החזרה שמקבל מופע של scaffold navigator ומציינים את backBehavior. ההגדרה הזו קובעת איך יעדים מוסרים מה-backstack במהלך ניווט אחורה. אחר כך מעבירים את scaffoldDirective ואת scaffoldState אל SupportingPaneScaffold. משתמשים בעומס יתר שמקבל ThreePaneScaffoldState, ומעבירים את scaffoldNavigator.scaffoldState.
מגדירים את החלוניות הראשיות והמשניות בתוך SupportingPaneScaffold. שימוש ב-AnimatedPane לאנימציות ברירת המחדל של החלונית.
אחרי שמבצעים את השלבים האלה, הקוד אמור להיראות בערך כך:
val scaffoldNavigator = rememberSupportingPaneScaffoldNavigator() val scope = rememberCoroutineScope() ThreePaneScaffoldPredictiveBackHandler( navigator = scaffoldNavigator, backBehavior = BackNavigationBehavior.PopUntilScaffoldValueChange ) SupportingPaneScaffold( directive = scaffoldNavigator.scaffoldDirective, scaffoldState = scaffoldNavigator.scaffoldState, mainPane = { MainPane( shouldShowSupportingPaneButton = scaffoldNavigator.scaffoldValue.secondary == PaneAdaptedValue.Hidden, onNavigateToSupportingPane = { scope.launch { scaffoldNavigator.navigateTo(ThreePaneScaffoldRole.Secondary) } } ) }, supportingPane = { SupportingPane(scaffoldNavigator = scaffoldNavigator) }, )