A paginação permite que os usuários deslizem na horizontal ou vertical entre páginas distintas em tela cheia nos dispositivos Wear OS. Casos de uso comuns incluem deslizar entre métricas de treino e controles de mídia em um app de exercícios ou navegar por fluxos de várias páginas.
No Compose para Wear OS Material 3, HorizontalPagerScaffold e
VerticalPagerScaffold coordenam o layout do pager, posicionando automaticamente
o indicador de página e gerenciando transições com TimeText.
Cada página é encapsulada em um elemento combinável AnimatedPage, que aplica
escalonamento, transformação de cantos arredondados e efeitos de tela escura à medida que as páginas transitam pela
tela redonda.
A animação a seguir mostra como HorizontalPagerScaffold e AnimatedPage
dimensionam e animam páginas durante deslizes horizontais:
Estrutura de hierarquia para paginação
Ao criar layouts de tela paginados no Material 3, seja deslizando para a esquerda ou direita (HorizontalPager) ou para cima ou para baixo (VerticalPager), use a seguinte hierarquia de componentes do contêiner externo para o conteúdo interno:
AppScaffold: o contêiner mais externo na raiz do seu app (use apenas um por app). Ele ancora a sobreposição globalTimeTextpara que o relógio permaneça parado na parte de cima da tela durante as transições de página e os gestos de deslizar para dispensar.HorizontalPagerScaffoldouVerticalPagerScaffold: colocado dentro deAppScaffoldno nível do pager. Ele coordena transições entreTimeTexteHorizontalPageIndicatorouVerticalPageIndicator.HorizontalPagerouVerticalPager: o contêiner do pager de base que gerencia gestos de deslizar, física de movimento rápido e entrada por seletor giratório usando umPagerStatecompartilhado.AnimatedPage: colocado dentro da lambda de conteúdo da página do pager. Ele encapsula cada página individual para aplicar animações de transição do Material Design 3 (efeitos de escalonamento e scrim) com base no deslocamento da página emPagerState.ScreenScaffold: colocado dentro deAnimatedPagepara cada página individual. Como cada página pode conter uma lista rolável vertical (como umTransformingLazyColumn) ou umEdgeButton, o aninhamento deScreenScaffoldem cada página garante que indicadores de rolagem vertical, botões de borda econtentPaddingpertençam a essa página específica e sejam animados de maneira suave com ela.
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)
Implementar um pager horizontal
Para implementar um pager horizontal no Material 3, aninhe HorizontalPagerScaffold,
HorizontalPager, AnimatedPage e ScreenScaffold dentro do
AppScaffold do seu app.
Use PagerScaffoldDefaults.snapWithSpringFlingBehavior para
flingBehavior e aplique a física de movimento de mola do Material 3 e o ajuste responsivo da página (HighSnapPositionalThreshold). Por padrão, HorizontalPager desativa
a rolagem da página com o seletor giratório (rotaryScrollableBehavior = null), permitindo que a coroa
ou o bisel giratório rolem listas verticais (como um
TransformingLazyColumn) dentro da página ativa.
O exemplo a seguir demonstra uma configuração completa de 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") } } } } } } } } }
Se uma página dentro do pager horizontal tiver um TransformingLazyColumn,
crie um rememberTransformingLazyColumnState() separado dentro do escopo
dessa página e transmita-o para o ScreenScaffold e o TransformingLazyColumn internos:
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") } } } } } } } } }
Implementar um pager vertical
Com um pager vertical, os usuários podem deslizar para cima e para baixo entre as páginas ou navegar por elas usando o botão lateral giratório ou o aro do relógio.
Ao contrário de HorizontalPager, o VerticalPager ativa o ajuste rotativo de página por
padrão (RotaryScrollableDefaults.snapBehavior(state)). Transmita
PagerScaffoldDefaults.snapWithSpringFlingBehavior para flingBehavior e encapsule
cada página em AnimatedPage e 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") } } } } } } }
Personalizar o comportamento do pager
É possível personalizar a sensibilidade de ajuste de HorizontalPagerScaffold e
VerticalPagerScaffold para corresponder às necessidades de interação do seu app.
Ajustar a sensibilidade do ajuste para treinos
Durante treinos ou atividades de alta intensidade em que o controle motor grosso do usuário é limitado, toques acidentais ou rotações leves da coroa podem mudar as páginas sem querer. Para essas telas, configure o pager com baixa sensibilidade de ajuste:
- Transmita
PagerDefaults.snapFlingBehaviorcommaxFlingPages = 0esnapPositionalThreshold = PagerScaffoldDefaults.LowSnapPositionalThresholdpara que seja necessário arrastar deliberadamente uma parte maior da tela para virar a página. - Se você ativar o ajuste de página rotativo, defina
snapSensitivity = RotaryScrollableDefaults.LowSnapSensitivityemRotaryScrollableDefaults.snapBehaviorpara exigir mais rotação antes de ajustar para a próxima página.
@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 } } } } } }
Para conferir implementações de amostra completas, consulte Pager.kt no repositório android/snippets
e PagerScaffoldSample.kt no repositório do AndroidX.