LazyRow — è una funzione composable in Jetpack Compose per creare liste orizzontali con caricamento lento degli elementi. A differenza di Row, LazyRow crea solo gli elementi visibili e li riutilizza durante lo scorrimento orizzontale. Secondo Google Android Documentation, 2025, LazyRow è l'equivalente orizzontale di LazyColumn ed è efficace per caroselli, gallerie e menu orizzontali in applicazioni mobili.
Punti chiave
LazyRow — è una funzione composable che implementa una lista orizzontale scorrevole con caricamento lento degli elementi. A differenza di Row, che renderizza tutti gli elementi figli contemporaneamente, LazyRow crea solo gli elementi visibili nell'area di visualizzazione.
LazyRow funziona con lo stesso principio di LazyColumn, ma dispone gli elementi orizzontalmente. Scorrendo a sinistra o a destra, gli elementi che escono dall'area di visualizzazione vengono riutilizzati per mostrarne di nuovi. Questo è criticamente importante per gallerie con molte immagini o lunghe liste di categorie.
Secondo Android Developers Blog, 2024, LazyRow utilizza la stessa architettura LazyList di LazyColumn, inclusi LazyListState, meccanismo di riutilizzo tramite Pool e supporto per diversi tipi di elementi. L'efficienza massima si ottiene con altezza fissa degli elementi.
LazyRow accetta i parametri modifier, state, contentPadding, reverseLayout, horizontalArrangement e verticalAlignment. Il contenuto viene definito tramite le funzioni DSL items e item, simile 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 gestisce la distribuzione degli elementi lungo l'asse orizzontale all'interno di LazyRow. Sono disponibili gli stessi valori Arrangement di Row: Start, Center, End, SpaceBetween, SpaceEvenly, SpaceAround e spacedBy con spaziatura personalizzata.
contentPadding aggiunge padding ai bordi del contenitore LazyRow. A differenza di Modifier.padding, contentPadding viene considerato durante lo scorrimento: il primo elemento avrà padding dal bordo sinistro, l'ultimo dal bordo destro. Secondo Material Design Guidelines, 2025, contentPadding è obbligatorio per caroselli e gallerie in modo che il primo e l'ultimo elemento non aderiscano al bordo dello schermo.
verticalAlignment allinea verticalmente gli elementi all'interno di LazyRow. Per impostazione predefinita viene utilizzato Alignment.Top. Per centrare elementi di diverse altezze, utilizzare Alignment.CenterVertically, utile per caroselli con immagini di diverse proporzioni.
| Parametro | Descrizione | Valore predefinito |
|---|---|---|
| horizontalArrangement | Distribuzione orizzontale degli elementi | Arrangement.Start |
| contentPadding | Padding ai bordi del contenitore | PaddingValues(0.dp) |
| verticalAlignment | Allineamento verticale | Alignment.Top |
| reverseLayout | Ordine inverso degli elementi | false |
| userScrollEnabled | Abilita scorrimento utente | true |
LazyListState per LazyRow funziona in modo identico a LazyColumn: tiene traccia del primo elemento visibile, dell'offset e della posizione generale di scorrimento. Lo stato viene creato tramite rememberLazyListState() e passato al parametro state.
Il controllo programmatico dello scorrimento di LazyRow viene effettuato con gli stessi metodi: animateScrollToItem per animazione fluida e scrollToItem per scorrimento istantaneo. Entrambi vengono chiamati all'interno di una coroutine. Questo è utile per caroselli con pulsanti avanti/indietro o per scorrimento automatico.
Secondo Android Developers, 2024, LazyRow supporta anche SnapFlingBehavior — un comportamento per lo scorrimento rapido che si ferma sull'elemento più vicino anziché tra gli elementi. Questo crea un effetto di snap familiare per caroselli e gallerie.
@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("Per iniziare") }
}
}
}
Il primo esempio — LazyRow per una galleria di immagini con anteprime. Ogni elemento è un Box con un'immagine e una didascalia. LazyRow gestisce efficacemente decine e centinaia di immagini, caricando solo quelle visibili.
@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)
)
}
}
}
Il secondo esempio — LazyRow per un elenco di categorie con icone. Le categorie vengono visualizzate come chip e l'utente può scorrerle orizzontalmente. LazyRow con spacedBy e contentPadding crea spaziatura tra le categorie e ai bordi.
@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 scelta tra LazyRow e Row dipende dal numero di elementi. Row è adatto per 5–10 elementi sempre visibili sullo schermo. LazyRow è essenziale quando ci sono molti elementi o il loro numero è dinamico.
Row renderizza tutti gli elementi contemporaneamente, causando ritardi con un gran numero di elementi. LazyRow renderizza solo quelli visibili, rendendolo preferibile per liste scorrevoli. Secondo Android Developers Blog, 2024, la soglia è di circa 10 elementi: se ci sono più elementi, usa LazyRow.
LazyRow supporta anche animazioni, SnapFlingBehavior e raggruppamento tramite separatori, rendendolo più flessibile per interfacce complesse. Row è più semplice e non richiede LazyListState, ma non è ottimizzato per liste lunghe.
Domande frequenti
LazyRow scorre orizzontalmente e dispone gli elementi da sinistra a destra, mentre LazyColumn scorre verticalmente dall'alto verso il basso. Entrambi utilizzano gli stessi principi di caricamento lento, LazyListState e funzioni DSL items.
Passa SnapFlingBehavior(listState) al parametro flingBehavior di LazyRow. SnapFlingBehavior forza LazyRow a fermarsi sull'elemento più vicino anziché tra gli elementi, creando un effetto di snap per caroselli.
Tieni traccia dell'ultimo elemento visibile tramite LazyListState.layoutInfo e carica nuovi dati quando l'ultimo elemento si avvicina alla fine della lista. Per lo scorrimento circolare, utilizza un'implementazione personalizzata con duplicazione degli elementi.
Sì, LazyRow può essere annidato all'interno di LazyColumn. Questo è un modello standard per creare pagine complesse con caroselli orizzontali all'interno di una lista verticale. Ogni LazyRow deve avere un'altezza fissa per funzionare correttamente.
Utilizza LazyListState.layoutInfo.visibleItemsInfo e confronta l'indice dell'ultimo elemento visibile con il totale meno uno. Quando questi valori coincidono, LazyRow si trova alla fine della lista.
Riepilogo
Svilupperemo un'applicazione mobile chiavi in mano
IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.
Leggi anche