Para desplazarte por el contenido en sentido izquierdo y derecho, o hacia arriba y abajo, puedes usar
el
HorizontalPager
y
VerticalPager
componibles, respectivamente. Estos elementos componibles tienen funciones similares a las siguientes:
ViewPager
en la vista
en un sistema de archivos. De forma predeterminada, el objeto HorizontalPager
ocupa todo el ancho de la pantalla.
VerticalPager
ocupa la altura completa, y los localizadores solo desplazan una página a la vez.
tiempo. Todos estos valores predeterminados se pueden configurar.
HorizontalPager
Para crear un localizador que se desplace horizontalmente a la izquierda y a la derecha, usa
HorizontalPager
// Display 10 items val pagerState = rememberPagerState(pageCount = { 10 }) HorizontalPager(state = pagerState) { page -> // Our page content Text( text = "Page: $page", modifier = Modifier.fillMaxWidth() ) }
VerticalPager
Para crear un localizador que se desplace hacia arriba y hacia abajo, usa VerticalPager
:
// Display 10 items val pagerState = rememberPagerState(pageCount = { 10 }) VerticalPager(state = pagerState) { page -> // Our page content Text( text = "Page: $page", modifier = Modifier.fillMaxWidth() ) }
Creación diferida
Las páginas de HorizontalPager
y VerticalPager
se desplazan de forma diferida
compuesta y dispuesta cuando sea necesario. Como usuario
se desplaza por las páginas, el elemento componible quita las que ya no
como en los productos necesarios.
Cargar más páginas fuera de pantalla
De forma predeterminada, el localizador solo carga las páginas visibles en pantalla. Cómo cargar más páginas
fuera de la pantalla, establece beyondBoundsPageCount
en un valor superior a cero.
Desplazarse hasta un elemento en el localizador
Para desplazarte a una página determinada en el paginador, crea un objeto PagerState
con rememberPagerState()
y pásalo como el parámetro state
al paginador. Puedes llamar
PagerState#scrollToPage()
en este estado, dentro de 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 quieres agregar una animación a la página, usa
PagerState#animateScrollToPage()
función:
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") }
Recibe notificaciones sobre los cambios en el estado de las páginas
PagerState
tiene tres propiedades con información sobre las páginas:
currentPage
,
settledPage
,
y
targetPage
.
currentPage
: Es la página más cercana a la posición de ajuste. De forma predeterminada, el ajuste está al comienzo del diseño.settledPage
: Es el número de página cuando no se está ejecutando ninguna animación ni desplazamiento. Esto es diferente de la propiedadcurrentPage
, ya quecurrentPage
se actualiza de inmediato si la página está lo suficientemente cerca de la posición de ajuste, perosettledPage
permanece igual hasta que se terminan de ejecutar todas las animaciones.targetPage
: Es la posición de parada propuesta para un movimiento de desplazamiento.
Puedes usar la función snapshotFlow
para observar los cambios en estas variables
y reaccionar a ellos. Por ejemplo, para enviar un evento de Analytics en cada cambio de página, puedes hacer lo siguiente:
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") }
Agrega un indicador de página
Para agregar un indicador a una página, usa el objeto PagerState
para obtener información.
sobre qué página se seleccionó del número de páginas y dibuja una
indicador.
Por ejemplo, si quieres un indicador
de círculo simple, puedes repetir el número de
círculos y cambiar el color de este si la página está seleccionada, mediante
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) ) } }
Aplica efectos de desplazamiento de elementos al contenido
Un caso de uso común consiste en usar la posición de desplazamiento para aplicar efectos a tu localizador
elementos. Para saber qué tan lejos está una página de la página seleccionada actualmente, puedes usar PagerState.currentPageOffsetFraction
.
Luego, puedes aplicar efectos de transformación a tu contenido según la distancia de la página seleccionada.
Por ejemplo, para ajustar la opacidad de los elementos según la distancia a la que se encuentren
central, cambia alpha
con
Modifier.graphicsLayer
en un elemento del localizador:
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 } }
Tamaños de página personalizados
De forma predeterminada, HorizontalPager
y VerticalPager
ocupan todo el ancho o
altura completa, respectivamente. Puedes configurar la variable pageSize
para que tenga un
Fixed
,
Fill
(predeterminado) o un cálculo de tamaño personalizado.
Por ejemplo, para establecer una página de ancho fijo de 100.dp
, haz lo siguiente:
val pagerState = rememberPagerState(pageCount = { 4 }) HorizontalPager( state = pagerState, pageSize = PageSize.Fixed(100.dp) ) { page -> // page content }
Para ajustar el tamaño de las páginas en función del tamaño del viewport, usa un tamaño de página personalizado
cálculo. Crea una
PageSize
objeto y divide el availableSpace
por tres teniendo en cuenta el espaciado
entre los elementos:
private val threePagesPerViewport = object : PageSize { override fun Density.calculateMainAxisPageSize( availableSpace: Int, pageSpacing: Int ): Int { return (availableSpace - 2 * pageSpacing) / 3 } }
Padding del contenido
Tanto HorizontalPager
como VerticalPager
admiten el cambio del padding del contenido,
lo que te permite influir en el tamaño máximo y la alineación de las páginas.
Por ejemplo, si se configura el padding de start
, las páginas se alinearán hacia el final:
val pagerState = rememberPagerState(pageCount = { 4 }) HorizontalPager( state = pagerState, contentPadding = PaddingValues(start = 64.dp), ) { page -> // page content }
Si estableces el padding de start
y end
en el mismo valor, el elemento se centra horizontalmente:
val pagerState = rememberPagerState(pageCount = { 4 }) HorizontalPager( state = pagerState, contentPadding = PaddingValues(horizontal = 32.dp), ) { page -> // page content }
Si estableces el padding de end
, se alinearán las páginas con el inicio:
val pagerState = rememberPagerState(pageCount = { 4 }) HorizontalPager( state = pagerState, contentPadding = PaddingValues(end = 64.dp), ) { page -> // page content }
Puedes establecer los valores top
y bottom
para lograr efectos similares para VerticalPager
. El valor 32.dp
solo se usa aquí como ejemplo. puedes configurar
cada una de las dimensiones de padding a cualquier valor.
Personaliza el comportamiento de desplazamiento
Los elementos HorizontalPager
y VerticalPager
predeterminados que admiten composición especifican cómo
los gestos de desplazamiento funcionan con el localizador. Sin embargo, puedes personalizar y cambiar
los valores predeterminados, como pagerSnapDistance
o flingBehavior
Distancia de ajuste
De forma predeterminada, HorizontalPager
y VerticalPager
establecen la cantidad máxima de
páginas por las que un gesto de deslizamiento se puede desplazar hasta una página a la vez. Para cambiar esto, establece pagerSnapDistance
en 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) } }
Recomendaciones para ti
- Nota: El texto del vínculo se muestra cuando JavaScript está desactivado
- ConstraintLayout en Compose
- Modificadores de gráficos
- Cómo migrar
CoordinatorLayout
a Compose