Pour faire défiler le contenu de gauche à droite ou de haut en bas, vous pouvez utiliser les composables HorizontalPager
et VerticalPager
, respectivement. Ces composables ont des fonctions similaires à celles de ViewPager
dans le système de vues. Par défaut, HorizontalPager
occupe toute la largeur de l'écran, VerticalPager
occupe toute la hauteur, et les paginations ne lancent qu'une seule page à la fois. Ces valeurs par défaut sont toutes configurables.
HorizontalPager
Pour créer un pager qui fait défiler les éléments horizontalement vers la gauche et la droite, utilisez HorizontalPager
:
// Display 10 items val pagerState = rememberPagerState(pageCount = { 10 }) HorizontalPager(state = pagerState) { page -> // Our page content Text( text = "Page: $page", modifier = Modifier.fillMaxWidth() ) }
VerticalPager
Pour créer un pager qui fait défiler la page vers le haut et vers le bas, utilisez VerticalPager
:
// Display 10 items val pagerState = rememberPagerState(pageCount = { 10 }) VerticalPager(state = pagerState) { page -> // Our page content Text( text = "Page: $page", modifier = Modifier.fillMaxWidth() ) }
Création différée
Les pages de HorizontalPager
et VerticalPager
sont composées de manière paresseuse et mises en page si nécessaire. Lorsque l'utilisateur fait défiler les pages, le composable supprime les pages qui ne sont plus nécessaires.
Charger d'autres pages en arrière-plan
Par défaut, le bipeur ne charge que les pages visibles à l'écran. Pour charger plus de pages en dehors de l'écran, définissez beyondBoundsPageCount
sur une valeur supérieure à zéro.
Faire défiler un élément dans le pager
Pour faire défiler le pager jusqu'à une page spécifique, créez un objet PagerState
à l'aide de rememberPagerState()
et transmettez-le en tant que paramètre state
au pager. Vous pouvez appeler PagerState#scrollToPage()
dans cet état, dans un CoroutineScope
:
val pagerState = rememberPagerState(pageCount = { 10 }) HorizontalPager(state = pagerState) { page -> // Our page content Text( text = "Page: $page", modifier = Modifier .fillMaxWidth() .height(100.dp) ) } // scroll to page val coroutineScope = rememberCoroutineScope() Button(onClick = { coroutineScope.launch { // Call scroll to on pagerState pagerState.scrollToPage(5) } }, modifier = Modifier.align(Alignment.BottomCenter)) { Text("Jump to Page 5") }
Si vous souhaitez animer la page, utilisez la fonction PagerState#animateScrollToPage()
:
val pagerState = rememberPagerState(pageCount = { 10 }) HorizontalPager(state = pagerState) { page -> // Our page content Text( text = "Page: $page", modifier = Modifier .fillMaxWidth() .height(100.dp) ) } // scroll to page val coroutineScope = rememberCoroutineScope() Button(onClick = { coroutineScope.launch { // Call scroll to on pagerState pagerState.animateScrollToPage(5) } }, modifier = Modifier.align(Alignment.BottomCenter)) { Text("Jump to Page 5") }
Recevoir des notifications concernant les modifications de l'état de la page
PagerState
comporte trois propriétés contenant des informations sur les pages : currentPage
, settledPage
et targetPage
.
currentPage
: page la plus proche de la position d'ancrage. Par défaut, la position d'ancrage se trouve au début de la mise en page.settledPage
: numéro de page lorsque l'animation ou le défilement ne sont pas en cours d'exécution. Cette valeur est différente de la propriétécurrentPage
, carcurrentPage
est immédiatement mise à jour si la page est suffisamment proche de la position d'ancrage, maissettledPage
reste la même jusqu'à la fin de l'exécution de toutes les animations.targetPage
: position d'arrêt proposée pour un mouvement de défilement.
Vous pouvez utiliser la fonction snapshotFlow
pour observer les modifications apportées à ces variables et y réagir. Par exemple, pour envoyer un événement Analytics à chaque changement de page, procédez comme suit:
val pagerState = rememberPagerState(pageCount = { 10 }) LaunchedEffect(pagerState) { // Collect from the a snapshotFlow reading the currentPage snapshotFlow { pagerState.currentPage }.collect { page -> // Do something with each page change, for example: // viewModel.sendPageSelectedEvent(page) Log.d("Page change", "Page changed to $page") } } VerticalPager( state = pagerState, ) { page -> Text(text = "Page: $page") }
Ajouter un indicateur de page
Pour ajouter un indicateur à une page, utilisez l'objet PagerState
pour obtenir des informations sur la page sélectionnée parmi le nombre de pages, puis dessinez votre indicateur personnalisé.
Par exemple, si vous souhaitez un indicateur de cercle simple, vous pouvez répéter le nombre de cercles et modifier leur couleur en fonction de la sélection de la page à l'aide de pagerState.currentPage
:
val pagerState = rememberPagerState(pageCount = { 4 }) HorizontalPager( state = pagerState, modifier = Modifier.fillMaxSize() ) { page -> // Our page content Text( text = "Page: $page", ) } Row( Modifier .wrapContentHeight() .fillMaxWidth() .align(Alignment.BottomCenter) .padding(bottom = 8.dp), horizontalArrangement = Arrangement.Center ) { repeat(pagerState.pageCount) { iteration -> val color = if (pagerState.currentPage == iteration) Color.DarkGray else Color.LightGray Box( modifier = Modifier .padding(2.dp) .clip(CircleShape) .background(color) .size(16.dp) ) } }
Appliquer des effets de défilement des éléments au contenu
Un cas d'utilisation courant consiste à utiliser la position de défilement pour appliquer des effets aux éléments de votre pager. Pour connaître la distance entre une page et la page actuellement sélectionnée, vous pouvez utiliser PagerState.currentPageOffsetFraction
.
Vous pouvez ensuite appliquer des effets de transformation à votre contenu en fonction de la distance par rapport à la page sélectionnée.
Par exemple, pour ajuster l'opacité des éléments en fonction de leur distance par rapport au centre, modifiez alpha
à l'aide de Modifier.graphicsLayer
sur un élément dans le pager:
val pagerState = rememberPagerState(pageCount = { 4 }) HorizontalPager(state = pagerState) { page -> Card( Modifier .size(200.dp) .graphicsLayer { // Calculate the absolute offset for the current page from the // scroll position. We use the absolute value which allows us to mirror // any effects for both directions val pageOffset = ( (pagerState.currentPage - page) + pagerState .currentPageOffsetFraction ).absoluteValue // We animate the alpha, between 50% and 100% alpha = lerp( start = 0.5f, stop = 1f, fraction = 1f - pageOffset.coerceIn(0f, 1f) ) } ) { // Card content } }
Tailles de page personnalisées
Par défaut, HorizontalPager
et VerticalPager
occupent respectivement toute la largeur ou la hauteur. Vous pouvez définir la variable pageSize
pour avoir un calcul Fixed
, Fill
(par défaut) ou un calcul de taille personnalisé.
Par exemple, pour définir une page à largeur fixe de 100.dp
:
val pagerState = rememberPagerState(pageCount = { 4 }) HorizontalPager( state = pagerState, pageSize = PageSize.Fixed(100.dp) ) { page -> // page content }
Pour dimensionner les pages en fonction de la taille de la fenêtre d'affichage, utilisez un calcul de taille de page personnalisé. Créez un objet PageSize
personnalisé et divisez la valeur availableSpace
par trois, en tenant compte de l'espacement entre les éléments:
private val threePagesPerViewport = object : PageSize { override fun Density.calculateMainAxisPageSize( availableSpace: Int, pageSpacing: Int ): Int { return (availableSpace - 2 * pageSpacing) / 3 } }
Marge intérieure du contenu
HorizontalPager
et VerticalPager
permettent tous deux de modifier la marge intérieure du contenu, ce qui vous permet d'influencer la taille maximale et l'alignement des pages.
Par exemple, définir la marge intérieure start
aligne les pages vers la fin:
val pagerState = rememberPagerState(pageCount = { 4 }) HorizontalPager( state = pagerState, contentPadding = PaddingValues(start = 64.dp), ) { page -> // page content }
Définir la marge intérieure start
et end
sur la même valeur centre l'élément horizontalement:
val pagerState = rememberPagerState(pageCount = { 4 }) HorizontalPager( state = pagerState, contentPadding = PaddingValues(horizontal = 32.dp), ) { page -> // page content }
Définir la marge intérieure end
aligne les pages vers le début:
val pagerState = rememberPagerState(pageCount = { 4 }) HorizontalPager( state = pagerState, contentPadding = PaddingValues(end = 64.dp), ) { page -> // page content }
Vous pouvez définir les valeurs top
et bottom
pour obtenir des effets similaires pour VerticalPager
. La valeur 32.dp
n'est utilisée ici qu'à titre d'exemple. Vous pouvez définir n'importe quelle valeur pour chacune des dimensions de marge intérieure.
Personnaliser le comportement de défilement
Les composables HorizontalPager
et VerticalPager
par défaut spécifient comment les gestes de défilement fonctionnent avec le pager. Toutefois, vous pouvez personnaliser et modifier les valeurs par défaut, telles que pagerSnapDistance
ou flingBehavior
.
Distance d'alignement
Par défaut, HorizontalPager
et VerticalPager
définissent le nombre maximal de pages qu'un geste de balayage peut faire défiler sur une seule page à la fois. Pour modifier cela, définissez pagerSnapDistance
sur flingBehavior
:
val pagerState = rememberPagerState(pageCount = { 10 }) val fling = PagerDefaults.flingBehavior( state = pagerState, pagerSnapDistance = PagerSnapDistance.atMost(10) ) Column(modifier = Modifier.fillMaxSize()) { HorizontalPager( state = pagerState, pageSize = PageSize.Fixed(200.dp), beyondViewportPageCount = 10, flingBehavior = fling ) { PagerSampleItem(page = it) } }
Recommandations personnalisées
- Remarque : Le texte du lien s'affiche lorsque JavaScript est désactivé
- ConstraintLayout dans Compose
- Modificateurs graphiques
- Migrer
CoordinatorLayout
vers Compose