LazyRow — es una función composable en Jetpack Compose para crear listas horizontales con carga diferida de elementos. A diferencia de Row, LazyRow crea solo los elementos visibles y los reutiliza durante el desplazamiento horizontal. Según Google Android Documentation, 2025, LazyRow es el equivalente horizontal de LazyColumn y es eficaz para carruseles, galerías y menús horizontales en aplicaciones móviles.
Puntos clave
LazyRow — es una función composable que implementa una lista horizontal desplazable con carga diferida de elementos. A diferencia de Row, que renderiza todos los elementos secundarios simultáneamente, LazyRow crea solo los elementos visibles en el área de visualización.
LazyRow funciona con el mismo principio que LazyColumn, pero dispone los elementos horizontalmente. Al desplazarse hacia la izquierda o la derecha, los elementos que salen del área de visualización se reutilizan para mostrar otros nuevos. Esto es críticamente importante para galerías con muchas imágenes o listas largas de categorías.
Según Android Developers Blog, 2024, LazyRow utiliza la misma arquitectura LazyList que LazyColumn, incluyendo LazyListState, el mecanismo de reutilización mediante Pool y el soporte para diferentes tipos de elementos. La máxima eficiencia se logra con una altura fija de los elementos.
LazyRow acepta los parámetros modifier, state, contentPadding, reverseLayout, horizontalArrangement y verticalAlignment. El contenido se define mediante las funciones DSL items y item, similar a LazyColumn.
@Composable
fun SimpleLazyRow() {
val items = (1..50).toList()
LazyRow(
modifier = Modifier.fillMaxWidth().height(100.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp),
contentPadding = PaddingValues(start = 16.dp, end = 16.dp)
) {
items(items) { item ->
Box(
modifier = Modifier.size(80.dp).background(Color.Gray)
) {
Text(text = "$item", modifier = Modifier.align(Alignment.Center))
}
}
}
}
horizontalArrangement gestiona la distribución de los elementos a lo largo del eje horizontal dentro de LazyRow. Están disponibles los mismos valores de Arrangement que en Row: Start, Center, End, SpaceBetween, SpaceEvenly, SpaceAround y spacedBy con espaciado personalizado.
contentPadding añade relleno en los bordes del contenedor LazyRow. A diferencia de Modifier.padding, contentPadding se tiene en cuenta durante el desplazamiento: el primer elemento tendrá relleno desde el borde izquierdo, el último desde el borde derecho. Según Material Design Guidelines, 2025, contentPadding es obligatorio para carruseles y galerías para que el primer y último elemento no se adhieran al borde de la pantalla.
verticalAlignment alinea los elementos verticalmente dentro de LazyRow. Por defecto se usa Alignment.Top. Para centrar elementos de diferentes alturas, use Alignment.CenterVertically, lo que es útil para carruseles con imágenes de diferentes proporciones.
| Parámetro | Descripción | Valor predeterminado |
|---|---|---|
| horizontalArrangement | Distribución horizontal de elementos | Arrangement.Start |
| contentPadding | Relleno en los bordes del contenedor | PaddingValues(0.dp) |
| verticalAlignment | Alineación vertical | Alignment.Top |
| reverseLayout | Orden inverso de elementos | false |
| userScrollEnabled | Habilitar desplazamiento del usuario | true |
LazyListState para LazyRow funciona de forma idéntica a LazyColumn: rastrea el primer elemento visible, el desplazamiento y la posición general de desplazamiento. El estado se crea mediante rememberLazyListState() y se pasa al parámetro state.
El control programático del desplazamiento de LazyRow se realiza con los mismos métodos: animateScrollToItem para animación suave y scrollToItem para desplazamiento instantáneo. Ambos se llaman dentro de una corrutina. Esto es útil para carruseles con botones de avance/retroceso o para desplazamiento automático.
Según Android Developers, 2024, LazyRow también admite SnapFlingBehavior — un comportamiento para desplazamiento rápido que se detiene en el elemento más cercano en lugar de entre elementos. Esto crea un efecto de ajuste familiar para carruseles y galerías.
@Composable
fun CarouselWithSnap() {
val listState = rememberLazyListState()
val scope = rememberCoroutineScope()
val items = listOf("A", "B", "C", "D", "E")
Column {
LazyRow(
state = listState,
flingBehavior = SnapFlingBehavior(listState),
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
items(items) { item ->
Card(modifier = Modifier.width(150.dp)) {
Text(text = item, modifier = Modifier.padding(16.dp))
}
}
}
Row(modifier = Modifier.fillMaxWidth()) {
Button(onClick = {
scope.launch {
listState.animateScrollToItem(0)
}
}) { Text("Para empezar") }
}
}
}
El primer ejemplo — LazyRow para una galería de imágenes con vistas previas. Cada elemento es un Box con una imagen y un pie de foto. LazyRow maneja eficientemente decenas y cientos de imágenes, cargando solo las visibles.
@Composable
fun ImageGallery(images: List<String>) {
LazyRow(
contentPadding = PaddingValues(start = 16.dp, end = 16.dp),
horizontalArrangement = Arrangement.spacedBy(12.dp)
) {
items(images, key = { it }) { url ->
AsyncImage(
model = url,
contentDescription = "Image",
modifier = Modifier.size(120.dp)
)
}
}
}
El segundo ejemplo — LazyRow para una lista de categorías con iconos. Las categorías se muestran como chips y el usuario puede desplazarlas horizontalmente. LazyRow con spacedBy y contentPadding crea espaciado entre categorías y en los bordes.
@Composable
fun CategoryChips(categories: List<String>) {
LazyRow(
contentPadding = PaddingValues(horizontal = 16.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
items(categories, key = { it }) { category ->
AssistChip(
onClick = {},
label = { Text(category) }
)
}
}
}
La elección entre LazyRow y Row depende del número de elementos. Row es adecuado para 5–10 elementos que siempre están visibles en la pantalla. LazyRow es esencial cuando hay muchos elementos o su cantidad es dinámica.
Row renderiza todos los elementos a la vez, lo que provoca retrasos con una gran cantidad de elementos. LazyRow renderiza solo los visibles, lo que lo hace preferible para listas desplazables. Según Android Developers Blog, 2024, el umbral es de aproximadamente 10 elementos: si hay más elementos, use LazyRow.
LazyRow también admite animaciones, SnapFlingBehavior y agrupación mediante separadores, lo que lo hace más flexible para interfaces complejas. Row es más simple y no requiere LazyListState, pero no está optimizado para listas largas.
Preguntas frecuentes
LazyRow se desplaza horizontalmente y dispone los elementos de izquierda a derecha, mientras que LazyColumn se desplaza verticalmente de arriba a abajo. Ambos utilizan los mismos principios de carga diferida, LazyListState y funciones DSL items.
Pase SnapFlingBehavior(listState) al parámetro flingBehavior de LazyRow. SnapFlingBehavior obliga a LazyRow a detenerse en el elemento más cercano en lugar de entre elementos, creando un efecto de ajuste para carruseles.
Rastree el último elemento visible mediante LazyListState.layoutInfo y cargue nuevos datos cuando el último elemento se acerque al final de la lista. Para desplazamiento circular, use una implementación personalizada con duplicación de elementos.
Sí, LazyRow se puede anidar dentro de LazyColumn. Este es un patrón estándar para crear páginas complejas con carruseles horizontales dentro de una lista vertical. Cada LazyRow debe tener una altura fija para un funcionamiento correcto.
Use LazyListState.layoutInfo.visibleItemsInfo y compare el índice del último elemento visible con el total menos uno. Cuando estos valores coinciden, LazyRow está al final de la lista.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también