החלפה בין דפים מאפשרת למשתמשים להחליק לרוחב או לאורך בין דפים נפרדים במסך מלא במכשירי Wear OS. תרחישי שימוש נפוצים כוללים החלקה בין מדדי אימון ואמצעי בקרה של מדיה באפליקציית אימון, או מעבר בין זרימות של כמה דפים.
ב-Compose for Wear OS Material 3, HorizontalPagerScaffold ו-VerticalPagerScaffold מתאמים את פריסת ה-pager, ממקמים אוטומטית את מחוון הדף ומנהלים את המעברים באמצעות TimeText.
כל דף עטוף ברכיב AnimatedPage שאפשר להוסיף לו, שמחיל אפקטים של שינוי גודל, שינוי צורה של פינות מעוגלות ושינוי צבע הרקע, כשעוברים בין דפים במסך העגול.
באנימציה הבאה אפשר לראות איך הדפים HorizontalPagerScaffold ו-AnimatedPage משנים את הגודל שלהם ומונפשים במהלך החלקה אופקית:
היררכיית Scaffold להחלפת דפים
כשמעצבים פריסות מסך עם חלוקה לדפים ב-Material 3 – בין אם מחליקים שמאלה או ימינה (HorizontalPager) או למעלה או למטה (VerticalPager) – משתמשים בהיררכיית הרכיבים הבאה מהמאגר החיצוני לתוכן הפנימי:
-
AppScaffold: הקונטיינר החיצוני ביותר בבסיס האפליקציה (אפשר להשתמש רק באחד לכל אפליקציה). הוא מעגן את שכבת העל הגלובליתTimeTextכך שהשעון יישאר קבוע בחלק העליון של המסך במהלך מעברים בין דפים ומחוות של החלקה לביטול. -
HorizontalPagerScaffoldאוVerticalPagerScaffold: ממוקם בתוךAppScaffoldברמת הדפדוף. הוא מתאם את המעברים ביןTimeTextלביןHorizontalPageIndicatorאוVerticalPageIndicator. -
HorizontalPagerאוVerticalPager: קונטיינר של רכיב החלפת הדפים הבסיסי שמנהל מחוות החלקה, פיזיקת הטלה וקליקים של חוגה להזנת נתונים באמצעותPagerStateמשותף. -
AnimatedPage: ממוקם בתוך פונקציית ה-lambda של תוכן הדף של רכיב ה-pager. הוא עוטף כל דף בנפרד כדי להחיל אנימציות מעבר של Material 3 (אפקטים של שינוי גודל ושל מסך חצי שקוף) על סמך ההיסט של הדף ב-PagerState. -
ScreenScaffold: התג הזה ממוקם בתוך התגAnimatedPageלכל דף בנפרד. מכיוון שכל דף יכול להכיל רשימה משלו עם אפשרות גלילה אנכית (כמוTransformingLazyColumn) אוEdgeButtonמשלו, הוספתScreenScaffoldבתוך כל דף מבטיחה שסמני הגלילה האנכית, לחצני הקצה ו-contentPaddingישתייכו לדף הספציפי הזה ויפעלו בצורה חלקה יחד איתו.
AppScaffold (1 per app: anchors global TimeText)
└── HorizontalPagerScaffold / VerticalPagerScaffold (manages PageIndicator)
└── HorizontalPager / VerticalPager (manages PagerState & fling behavior)
└── AnimatedPage (applies scaling & scrim transitions per page)
└── ScreenScaffold (1 per page: ScrollIndicator & EdgeButton)
└── Page Content (Column or TransformingLazyColumn)
הטמעה של תצוגת דפים אופקית
כדי להטמיע רכיב pager אופקי ב-Material 3, צריך להוסיף את הרכיבים HorizontalPagerScaffold,
HorizontalPager, AnimatedPage ו-ScreenScaffold בתוך הרכיב AppScaffold של האפליקציה.
משתמשים ב-PagerScaffoldDefaults.snapWithSpringFlingBehavior בשביל flingBehavior כדי להחיל פיזיקה של תנועת קפיץ Material 3 והצמדה רספונסיבית של דפים (HighSnapPositionalThreshold). כברירת מחדל, HorizontalPager משבית את הגלילה הסיבובית של הדפים (rotaryScrollableBehavior = null), ומאפשר להשתמש בסיבוב של הכתר או המסגרת כדי לגלול ברשימות אנכיות (כמו TransformingLazyColumn) בתוך הדף הפעיל.
בדוגמה הבאה מוצגת הגדרה מלאה של HorizontalPagerScaffold:
@Composable fun HorizontalPagerScaffoldSample(navigateBack: () -> Unit) { AppScaffold { val pagerState = rememberPagerState(pageCount = { 10 }) HorizontalPagerScaffold(pagerState = pagerState) { HorizontalPager( state = pagerState, flingBehavior = PagerScaffoldDefaults.snapWithSpringFlingBehavior( state = pagerState ), ) { page -> AnimatedPage(pageIndex = page, pagerState = pagerState) { ScreenScaffold { Column( modifier = Modifier.fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center, ) { Text(text = "Page #$page") Spacer(modifier = Modifier.height(8.dp)) Text(text = "Swipe left and right") if (page == 0) { Spacer(modifier = Modifier.height(16.dp)) Button(onClick = navigateBack) { Text("Exit") } } } } } } } } }
אם דף בתוך רכיב ה-pager האופקי מכיל TransformingLazyColumn, צריך ליצור rememberTransformingLazyColumnState() נפרד בהיקף של הדף הזה ולהעביר אותו אל ScreenScaffold ו-TransformingLazyColumn הפנימיים:
AppScaffold { val pagerState = rememberPagerState(pageCount = { 10 }) HorizontalPagerScaffold(pagerState = pagerState) { HorizontalPager( state = pagerState, flingBehavior = PagerScaffoldDefaults.snapWithSpringFlingBehavior( state = pagerState ), ) { page -> AnimatedPage(pageIndex = page, pagerState = pagerState) { val columnState = rememberTransformingLazyColumnState() val transformationSpec = rememberTransformationSpec() ScreenScaffold( scrollState = columnState, ) { contentPadding -> TransformingLazyColumn( state = columnState, contentPadding = contentPadding, ) { item { ListHeader( modifier = Modifier .fillMaxWidth() .transformedHeight(this, transformationSpec) .minimumVerticalContentPadding( ListHeaderDefaults.minimumTopListContentPadding ), transformation = SurfaceTransformation(transformationSpec), ) { Text(text = "Pager sample") } } item { Card( modifier = Modifier .fillMaxWidth() .transformedHeight(this, transformationSpec) .minimumVerticalContentPadding( CardDefaults.minimumVerticalListContentPadding ), transformation = SurfaceTransformation(transformationSpec), ) { if (page == 0) { Text(text = "Page #$page. Swipe right") } else { Text(text = "Page #$page. Swipe left and right") } } } } } } } } }
הטמעה של תצוגת דפים אנכית
בכלי לניווט אנכי בין דפים, המשתמשים יכולים להחליק למעלה ולמטה כדי לעבור בין הדפים או להשתמש בלחצן הצדדי המסתובב או במסגרת של השעון כדי לעבור בין הדפים.
בניגוד ל-HorizontalPager, VerticalPager מאפשרת הצמדה סיבובית של דפים כברירת מחדל (RotaryScrollableDefaults.snapBehavior(state)). מעבירים את PagerScaffoldDefaults.snapWithSpringFlingBehavior אל flingBehavior ועוטפים כל דף ב-AnimatedPage וב-ScreenScaffold:
@Composable fun VerticalPagerScaffoldSample() { AppScaffold { val pagerState = rememberPagerState(pageCount = { 10 }) VerticalPagerScaffold(pagerState = pagerState) { VerticalPager( state = pagerState, flingBehavior = PagerScaffoldDefaults.snapWithSpringFlingBehavior( state = pagerState ), ) { page -> AnimatedPage(pageIndex = page, pagerState = pagerState) { ScreenScaffold { Column( modifier = Modifier.fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center, ) { Text(text = "Page #$page") Spacer(modifier = Modifier.height(8.dp)) Text(text = "Swipe up and down") } } } } } } }
התאמה אישית של התנהגות מכשיר הפייג'ר
אתם יכולים לשנות את מידת הרגישות של ההצמדה של HorizontalPagerScaffold ושל VerticalPagerScaffold בהתאם לצרכים של האינטראקציה עם האפליקציה.
שינוי מידת הרגישות של ההצמדה לאימונים
במהלך אימונים או פעילויות עם תנועות רבות שבהן השליטה המוטורית הגסה של המשתמש מוגבלת, מגעים מקריים או סיבובים קלים של הכתר עלולים להוביל למעבר לא מכוון בין דפים. במסכים האלה, צריך להגדיר את מכשיר הביפר עם רגישות נמוכה לשינוי מיקום:
- כדי להעביר את
PagerDefaults.snapFlingBehaviorעםmaxFlingPages = 0ו-snapPositionalThreshold = PagerScaffoldDefaults.LowSnapPositionalThreshold, צריך לגרור בכוונה חלק גדול יותר של המסך כדי להעביר את הדף. - אם מפעילים את ההגדרה 'הצמדת דפים בסיבוב', צריך להגדיר את
snapSensitivity = RotaryScrollableDefaults.LowSnapSensitivityב-RotaryScrollableDefaults.snapBehaviorכדי לדרוש סיבוב נוסף לפני ההצמדה לדף הבא.
@Composable fun HorizontalPagerScaffoldWithLowSensitivitySample(navigateBack: () -> Unit) { AppScaffold { val pagerState = rememberPagerState(pageCount = { 3 }) HorizontalPagerScaffold(pagerState = pagerState) { HorizontalPager( state = pagerState, flingBehavior = PagerDefaults.snapFlingBehavior( state = pagerState, maxFlingPages = 0, snapPositionalThreshold = PagerScaffoldDefaults.LowSnapPositionalThreshold, ), rotaryScrollableBehavior = RotaryScrollableDefaults.snapBehavior( pagerState = pagerState, snapSensitivity = RotaryScrollableDefaults.LowSnapSensitivity, ), ) { page -> AnimatedPage(pageIndex = page, pagerState = pagerState) { ScreenScaffold { // Page content } } } } } }
דוגמאות מלאות להטמעה זמינות ב-Pager.kt במאגר android/snippets וב-PagerScaffoldSample.kt במאגר AndroidX.