LazyRow — to funkcja composable w Jetpack Compose do tworzenia poziomych list z leniwym ładowaniem elementów. W przeciwieństwie do Row, LazyRow tworzy tylko widoczne elementy i ponownie je wykorzystuje podczas przewijania w poziomie. Według Google Android Documentation, 2025, LazyRow jest poziomym odpowiednikiem LazyColumn i jest efektywny dla karuzel, galerii i poziomych menu w aplikacjach mobilnych.
Najważniejsze
LazyRow — to funkcja composable implementująca poziomą przewijaną listę z leniwym ładowaniem elementów. W przeciwieństwie do Row, który renderuje wszystkie elementy potomne jednocześnie, LazyRow tworzy tylko elementy widoczne w obszarze wyświetlania.
LazyRow działa na tej samej zasadzie co LazyColumn, ale rozmieszcza elementy poziomo. Podczas przewijania w lewo lub w prawo elementy, które wyszły z obszaru widoku, są ponownie wykorzystywane do wyświetlania nowych. Jest to krytycznie ważne dla galerii z dużą liczbą obrazów lub długich list kategorii.
Według Android Developers Blog, 2024, LazyRow używa tej samej architektury LazyList co LazyColumn, włączając w to LazyListState, mechanizm ponownego wykorzystania przez Pool i obsługę różnych typów elementów. Maksymalną efektywność osiąga się przy użyciu stałej wysokości elementów.
LazyRow przyjmuje parametry modifier, state, contentPadding, reverseLayout, horizontalArrangement i verticalAlignment. Zawartość jest definiowana za pomocą funkcji DSL items i item, podobnie jak w 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 zarządza rozmieszczeniem elementów wzdłuż osi poziomej wewnątrz LazyRow. Dostępne są te same wartości Arrangement co w Row: Start, Center, End, SpaceBetween, SpaceEvenly, SpaceAround i spacedBy z niestandardowym odstępem.
contentPadding dodaje odstępy na krawędziach kontenera LazyRow. W przeciwieństwie do Modifier.padding, contentPadding jest uwzględniany podczas przewijania: pierwszy element będzie miał odstęp od lewej krawędzi, ostatni — od prawej. Według Material Design Guidelines, 2025, contentPadding jest obowiązkowy dla karuzel i galerii, aby pierwszy i ostatni element nie przylegały do krawędzi ekranu.
verticalAlignment wyrównuje elementy w pionie wewnątrz LazyRow. Domyślnie używane jest Alignment.Top. Do centrowania elementów o różnej wysokości używaj Alignment.CenterVertically, co jest przydatne dla karuzel z obrazami o różnych proporcjach.
| Parametr | Opis | Wartość domyślna |
|---|---|---|
| horizontalArrangement | Rozmieszczenie elementów w poziomie | Arrangement.Start |
| contentPadding | Odstępy na krawędziach kontenera | PaddingValues(0.dp) |
| verticalAlignment | Wyrównanie w pionie | Alignment.Top |
| reverseLayout | Odwrócona kolejność elementów | false |
| userScrollEnabled | Zezwolenie na przewijanie przez użytkownika | true |
LazyListState dla LazyRow działa identycznie jak dla LazyColumn: śledzi pierwszy widoczny element, przesunięcie i ogólną pozycję przewijania. Stan jest tworzony przez rememberLazyListState() i przekazywany w parametrze state.
Programowe sterowanie przewijaniem LazyRow odbywa się tymi samymi metodami: animateScrollToItem dla płynnej animacji i scrollToItem dla natychmiastowego przewijania. Obie są wywoływane wewnątrz korutyny. Jest to przydatne dla karuzel z przyciskami „W lewo/W prawo" lub do automatycznego przewijania.
Według Android Developers, 2024, LazyRow obsługuje również SnapFlingBehavior — zachowanie przy gwałtownym przewijaniu, które zatrzymuje się na najbliższym elemencie, a nie między elementami. Tworzy to efekt „przyklejania" do elementu, znany z karuzel i galerii.
@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("Aby rozpocząć") }
}
}
}
Pierwszy przykład — LazyRow dla galerii obrazów z podglądami. Każdy element to Box z obrazem i podpisem. LazyRow efektywnie obsługuje dziesiątki i setki obrazów, ładując tylko widoczne.
@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)
)
}
}
}
Drugi przykład — LazyRow dla listy kategorii z ikonami. Kategorie są wyświetlane w formie chipów, a użytkownik może przewijać je poziomo. LazyRow z spacedBy i contentPadding tworzy odstępy między kategoriami i na krawędziach.
@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) }
)
}
}
}
Wybór między LazyRow a Row zależy od liczby elementów. Row nadaje się dla 5–10 elementów, które są zawsze widoczne na ekranie. LazyRow jest obowiązkowy, gdy elementów jest wiele lub ich liczba jest dynamiczna.
Row renderuje wszystkie elementy naraz, co prowadzi do opóźnień przy dużej liczbie elementów. LazyRow renderuje tylko widoczne, co czyni go preferowanym dla list z przewijaniem. Według Android Developers Blog, 2024, próg przejścia to około 10 elementów: jeśli elementów jest więcej, używaj LazyRow.
LazyRow obsługuje również animacje, SnapFlingBehavior i grupowanie przez separatory, co czyni go bardziej elastycznym dla złożonych interfejsów. Row jest prostszy i nie wymaga LazyListState, ale nie jest zoptymalizowany dla długich list.
Często zadawane pytania
LazyRow przewija się poziomo i rozmieszcza elementy od lewej do prawej, a LazyColumn — pionowo z góry na dół. Oba używają tych samych zasad leniwego ładowania, LazyListState i funkcji DSL items.
Przekaż SnapFlingBehavior(listState) w parametrze flingBehavior LazyRow. SnapFlingBehaviour powoduje, że LazyRow zatrzymuje się na najbliższym elemencie, a nie między elementami, co tworzy efekt przyklejania dla karuzel.
Śledź ostatni widoczny element przez LazyListState.layoutInfo i ładuj nowe dane, gdy ostatni element zbliża się do końca listy. Do cyklicznego przewijania użyj niestandardowej implementacji z duplikowaniem elementów.
Tak, LazyRow można zagnieżdżać w LazyColumn. Jest to standardowy wzorzec do tworzenia złożonych stron z poziomymi karuzelami wewnątrz pionowej listy. Każdy LazyRow powinien mieć stałą wysokość do poprawnego działania.
Użyj LazyListState.layoutInfo.visibleItemsInfo i porównaj indeks ostatniego widocznego elementu z całkowitą liczbą minus jeden. Gdy te wartości się pokrywają, LazyRow znajduje się na końcu listy.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również