Modificadores de desplazamiento
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 del desplazamiento u obtener 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 fundamental para crear contenedores desplazables personalizados. Proporciona una abstracción de nivel superior sobre el modificador scrollable, ya que controla requisitos comunes, como la interpretación del delta de gestos, el recorte de contenido y los efectos de desplazamiento excesivo.
Si bien scrollableArea se usa para implementaciones personalizadas, en 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 simples para los casos de uso comunes y se compilan con scrollableArea.
Diferencia entre los modificadores de 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., arrastre del puntero) en la pantalla.scrollableArea(delta orientado al contenido): Eldeltase invierte semánticamente para representar el cambio seleccionado en la posición de desplazamiento y hacer que el contenido parezca moverse con el gesto del usuario, que suele ser lo contrario del movimiento del puntero.
Piensa en ello 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 la razón por la 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 del 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 según los límites del diseño y controla la renderización de los efectos de desplazamiento excesivo. De forma predeterminada, se usa el efecto proporcionado por 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 pueda usar adecuadamente con los modificadores horizontalScroll o verticalScroll, o con los diseños Lazy. A menudo, esto implica 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: Aplicar transformaciones, ajustes de escala u otros efectos a los elementos secundarios a medida que se desplazan.
- Control directo: Necesitas un control detallado sobre la mecánica de desplazamiento más allá de lo que exponen
verticalScrollo los diseños Lazy.
Crea listas personalizadas similares a ruedas con scrollableArea
En el siguiente ejemplo, se muestra el uso de scrollableArea para compilar una lista vertical personalizada en la que los elementos se reducen a medida que se alejan del centro, lo que crea un efecto visual similar a una rueda. Este tipo de transformación dependiente 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 porque scrollable detecta los gestos de desplazamiento y captura los deltas, pero no desplaza su contenido automáticamente. En cambio, 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 invoque en cada paso de desplazamiento (con entrada de gestos, desplazamiento suave o arrastrar y soltar) con el delta en píxeles. Esta función debe devolver 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 Views en Compose