Los selectores verticalScroll y horizontalScroll proporcionan la forma más sencilla de permitir que el usuario se desplace por un elemento cuando los límites del contenido sean más grandes que las restricciones de tamaño máximo. Con los modificadores verticalScroll y horizontalScroll, no necesitas traducir ni compensar el contenido.
@Composable private fun ScrollBoxes() { Column( modifier = Modifier .background(Color.LightGray) .size(100.dp) .verticalScroll(rememberScrollState()) ) { repeat(10) { Text("Item $it", modifier = Modifier.padding(2.dp)) } } }
ScrollState te permite cambiar la posición de desplazamiento o conocer su estado actual. Para crearlo con los parámetros predeterminados, usa rememberScrollState().
@Composable private fun ScrollBoxesSmooth() { // Smoothly scroll 100px on first composition val state = rememberScrollState() LaunchedEffect(Unit) { state.animateScrollTo(100) } Column( modifier = Modifier .background(Color.LightGray) .size(100.dp) .padding(horizontal = 8.dp) .verticalScroll(state) ) { repeat(10) { Text("Item $it", modifier = Modifier.padding(2.dp)) } } }
Modificador de área desplazable
El modificador scrollableArea es un componente básico fundamental para crear contenedores desplazables personalizados. Proporciona una abstracción de nivel superior sobre el modificador scrollable, que controla los requisitos comunes, como la interpretación de diferencias de gestos, el recorte de contenido y los efectos de sobredesplazamiento.
Si bien scrollableArea se usa para implementaciones personalizadas, por lo general, deberías preferir soluciones listas para usar, como verticalScroll, horizontalScroll o elementos componibles, como LazyColumn, para las listas de desplazamiento estándar. Estos componentes de nivel superior son más sencillos para los casos de uso comunes y se compilan con scrollableArea.
Diferencia entre los modificadores scrollableArea y scrollable
La principal diferencia entre scrollableArea y scrollable radica en cómo interpretan los gestos de desplazamiento del usuario:
scrollable(delta sin procesar): El delta refleja directamente el movimiento físico de la entrada del usuario (p.ej., arrastrar el puntero) en la pantalla.scrollableArea(delta orientado al contenido): Eldeltase invierte de forma semántica para representar el cambio seleccionado en la posición de desplazamiento para que el contenido parezca moverse con el gesto del usuario, que suele ser lo opuesto al movimiento del puntero.
Piensa en esto de la siguiente manera: scrollable te indica cómo se movió el puntero, mientras que scrollableArea traduce ese movimiento del puntero en cómo se debe mover el contenido dentro de una vista desplazable típica. Esta inversión es el motivo por el que scrollableArea se siente más natural cuando se implementa un contenedor desplazable estándar.
En la siguiente tabla, se resumen los signos delta para situaciones comunes:
Gesto del usuario |
delta informado a |
delta informado a |
|---|---|---|
El puntero se mueve HACIA ARRIBA |
Negativo |
Positivo |
El puntero se mueve HACIA ABAJO |
Positivo |
Negativo |
El puntero se mueve hacia la IZQUIERDA. |
Negativo |
Positivo (negativo para RTL) |
El puntero se mueve hacia la DERECHA |
Positivo |
Negativo (positivo para RTL) |
(*) Nota sobre el signo delta de scrollableArea: El signo del delta de scrollableArea no es solo una inversión simple. Considera de forma inteligente lo siguiente:
- Orientación: Vertical u horizontal.
LayoutDirection: De izquierda a derecha o de derecha a izquierda (especialmente importante para el desplazamiento horizontal).- Marca
reverseScrolling: Indica si se invierte la dirección de desplazamiento.
Además de invertir el delta de desplazamiento, scrollableArea también recorta el contenido a los límites del diseño y controla la renderización de los efectos de sobredesplazamiento. De forma predeterminada, usa el efecto que proporciona LocalOverscrollFactory.
Puedes personalizar o inhabilitar esta opción con la sobrecarga scrollableArea que acepta un parámetro OverscrollEffect.
Cuándo usar el modificador scrollableArea
Debes usar el modificador scrollableArea cuando necesites compilar un componente de desplazamiento personalizado que no se entregue de forma adecuada con los modificadores horizontalScroll o verticalScroll, o bien con los diseños Lazy. Esto suele implicar casos con las siguientes características:
- Lógica de diseño personalizada: Cuando la disposición de los elementos cambia de forma dinámica según la posición de desplazamiento.
- Efectos visuales únicos: Aplica transformaciones, escalamiento o cualquier otro efecto a los elementos secundarios a medida que se desplazan.
- Control directo: Necesitas un control detallado de los mecanismos de desplazamiento más allá de lo que exponen
verticalScrollo los diseños diferidos.
Crea listas personalizadas similares a ruedas con scrollableArea
En el siguiente ejemplo, se muestra cómo usar scrollableArea para compilar una lista vertical personalizada en la que los elementos se reducen verticalmente a medida que se alejan del centro, lo que crea un efecto visual similar a una rueda. Este tipo de transformación que depende del desplazamiento es un caso de uso perfecto para scrollableArea.
scrollableArea
@Composable private fun ScrollableAreaSample() { // ... Layout( modifier = Modifier .size(150.dp) .scrollableArea(scrollState, Orientation.Vertical) .background(Color.LightGray), // ... ) { measurables, constraints -> // ... // Update the maximum scroll value to not scroll beyond limits and stop when scroll // reaches the end. scrollState.maxValue = (totalHeight - viewportHeight).coerceAtLeast(0) // Position the children within the layout. layout(constraints.maxWidth, viewportHeight) { // The current vertical scroll position, in pixels. val scrollY = scrollState.value val viewportCenterY = scrollY + viewportHeight / 2 var placeableLayoutPositionY = 0 placeables.forEach { placeable -> // This sample applies a scaling effect to items based on their distance // from the center, creating a wheel-like effect. // ... // Place the item horizontally centered with a layer transformation for // scaling to achieve wheel-like effect. placeable.placeRelativeWithLayer( x = constraints.maxWidth / 2 - placeable.width / 2, // Offset y by the scroll position to make placeable visible in the viewport. y = placeableLayoutPositionY - scrollY, ) { scaleX = scaleFactor scaleY = scaleFactor } // Move to the next item's vertical position. placeableLayoutPositionY += placeable.height } } } } // ...
Modificador desplazable
El modificador scrollable difiere de los modificadores de desplazamiento en que scrollable detecta los gestos de desplazamiento y captura los deltas, pero no compensa su contenido automáticamente. En cambio, esto se delega al usuario a través de ScrollableState, que es necesario para que este modificador funcione correctamente.
Cuando construyas ScrollableState, debes proporcionar una función consumeScrollDelta que se invocará en cada paso de desplazamiento (por entrada de gesto, desplazamiento fluido o deslizamiento rápido) con el delta en píxeles. Esta función debe mostrar la cantidad de distancia de desplazamiento consumida para garantizar que el evento se propague correctamente en los casos en que haya elementos anidados que tengan el modificador scrollable.
En el siguiente fragmento, se detectan los gestos y se muestra un valor numérico para un desplazamiento, pero no se desplaza ningún elemento:
@Composable private fun ScrollableSample() { // actual composable state var offset by remember { mutableFloatStateOf(0f) } Box( Modifier .size(150.dp) .scrollable( orientation = Orientation.Vertical, // Scrollable state: describes how to consume // scrolling delta and update offset state = rememberScrollableState { delta -> offset += delta delta } ) .background(Color.LightGray), contentAlignment = Alignment.Center ) { Text(offset.toString()) } }
Recomendaciones para ti
- Nota: El texto del vínculo se muestra cuando JavaScript está desactivado
- Información sobre los gestos
- Migra
CoordinatorLayouta Compose - Cómo usar objetos View en Compose