Mit der Paging-Funktion können Nutzer auf Wear OS-Geräten horizontal oder vertikal zwischen verschiedenen Vollbildseiten wischen. Häufige Anwendungsfälle sind das Wischen zwischen Trainingsmesswerten und Mediensteuerungen in einer Trainings-App oder das Durchlaufen mehrseitiger Abläufe.
In Compose für Wear OS Material 3 koordinieren HorizontalPagerScaffold und VerticalPagerScaffold das Pager-Layout. Der Seitenindikator wird automatisch positioniert und Übergänge werden mit TimeText verwaltet.
Jede Seite ist in ein AnimatedPage-Composable eingeschlossen, das beim Übergang von Seiten auf dem runden Display Skalierung, Morphing von abgerundeten Ecken und Scrim-Effekte anwendet.
Die folgende Animation zeigt, wie HorizontalPagerScaffold und AnimatedPage Seiten bei horizontalen Wischbewegungen skalieren und animieren:
Gerüst für die Paginierung erstellen
Wenn Sie in Material 3 Layouts mit Seitennavigation entwerfen – unabhängig davon, ob Sie nach links oder rechts (HorizontalPager) oder nach oben oder unten (VerticalPager) wischen –, verwenden Sie die folgende Komponentenstruktur vom äußeren Container bis zum inneren Inhalt:
AppScaffold: Der äußerste Container im Stammverzeichnis Ihrer App (nur einer pro App). Dadurch wird das globaleTimeText-Overlay fixiert, sodass die Uhr bei Seitenübergängen und Wischgesten zum Schließen oben auf dem Display bleibt.HorizontalPagerScaffoldoderVerticalPagerScaffold: Wird auf Pager-Ebene inAppScaffoldplatziert. Sie koordiniert Übergänge zwischenTimeTextundHorizontalPageIndicatoroderVerticalPageIndicator.HorizontalPageroderVerticalPager: Der Foundation-Pager-Container, der Wischbewegungen, Fling-Physik und das Einrasten bei der Dreheingabe mithilfe eines gemeinsamenPagerStateverwaltet.AnimatedPage: Wird in der Lambda-Funktion für den Seiteninhalt des Pagers platziert. Sie umschließt jede einzelne Seite, um basierend auf dem Offset der Seite inPagerStateMaterial 3-Übergangsanimationen (Skalierungs- und Scrim-Effekte) anzuwenden.ScreenScaffold: Wird innerhalb vonAnimatedPagefür jede einzelne Seite platziert. Da jede Seite eine eigene vertikal scrollbare Liste (z. B. eineTransformingLazyColumn) oder ein eigenesEdgeButtonenthalten kann, wird durch das Einbetten vonScreenScaffoldauf jeder Seite dafür gesorgt, dass vertikale Scrollindikatoren, Schaltflächen am Rand undcontentPaddingzu dieser Seite gehören und sich reibungslos mit ihr animieren lassen.
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)
Horizontalen Pager implementieren
Wenn Sie einen horizontalen Pager in Material 3 implementieren möchten, verschachteln Sie HorizontalPagerScaffold, HorizontalPager, AnimatedPage und ScreenScaffold in der AppScaffold Ihrer App.
Verwende PagerScaffoldDefaults.snapWithSpringFlingBehavior für flingBehavior, um die Physik der Material 3-Federbewegung und das responsive Andocken von Seiten (HighSnapPositionalThreshold) anzuwenden. Standardmäßig wird durch HorizontalPager das Scrollen von Seiten mit der drehbaren Lünette (rotaryScrollableBehavior = null) deaktiviert. So kann durch Drehen der Krone oder Lünette in vertikalen Listen (z. B. in einem TransformingLazyColumn) auf der aktiven Seite gescrollt werden.
Im folgenden Beispiel wird eine vollständige HorizontalPagerScaffold-Einrichtung veranschaulicht:
@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") } } } } } } } } }
Wenn eine Seite in Ihrem horizontalen Pager ein TransformingLazyColumn enthält, erstellen Sie ein separates rememberTransformingLazyColumnState() innerhalb des Bereichs dieser Seite und übergeben Sie es an das innere ScreenScaffold und 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") } } } } } } } } }
Vertikale Seite implementieren
Mit einem vertikalen Pager können Nutzer durch Wischen nach oben und unten zwischen Seiten wechseln oder die drehbare Seitentaste oder Lünette der Smartwatch verwenden, um die Seiten durchzugehen.
Im Gegensatz zu HorizontalPager wird bei VerticalPager standardmäßig das Einrasten von Seiten beim Drehen aktiviert (RotaryScrollableDefaults.snapBehavior(state)). Übergeben Sie PagerScaffoldDefaults.snapWithSpringFlingBehavior an flingBehavior und umschließen Sie jede Seite mit AnimatedPage und 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") } } } } } } }
Pager-Verhalten anpassen
Sie können die Einrastempfindlichkeit von HorizontalPagerScaffold und VerticalPagerScaffold an die Interaktionsanforderungen Ihrer App anpassen.
Empfindlichkeit für das Einrasten bei Trainings anpassen
Bei Trainings oder Aktivitäten mit starken Bewegungen, bei denen die grobmotorische Kontrolle des Nutzers eingeschränkt ist, kann es durch versehentliche Berührungen oder leichte Kronendrehungen zu einem unbeabsichtigten Seitenwechsel kommen. Konfigurieren Sie für diese Bildschirme den Pager mit einer geringen Einrastempfindlichkeit:
- Übergeben Sie
PagerDefaults.snapFlingBehaviormitmaxFlingPages = 0undsnapPositionalThreshold = PagerScaffoldDefaults.LowSnapPositionalThreshold. Zum Umblättern ist also ein bewusstes Ziehen über einen größeren Teil des Displays erforderlich. - Wenn Sie das Einrasten von Seiten beim Drehen aktivieren, legen Sie
snapSensitivity = RotaryScrollableDefaults.LowSnapSensitivityinRotaryScrollableDefaults.snapBehaviorfest, um mehr Drehung zu erfordern, bevor zur nächsten Seite gewechselt wird.
@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 } } } } } }
Vollständige Beispielimplementierungen finden Sie unter Pager.kt im android/snippets-Repository und unter PagerScaffoldSample.kt im AndroidX-Repository.