LazyRow — là một hàm composable trong Jetpack Compose để tạo danh sách ngang với tải chậm các phần tử. Không giống như Row, LazyRow chỉ tạo các phần tử hiển thị và tái sử dụng chúng trong khi cuộn ngang. Theo Google Android Documentation, 2025, LazyRow là phiên bản ngang của LazyColumn và hiệu quả cho carousel, thư viện ảnh và menu ngang trong ứng dụng di động.
Những điểm chính
LazyRow — là một hàm composable triển khai danh sách ngang có thể cuộn với tải chậm các phần tử. Không giống như Row, nơi render tất cả các phần tử con cùng lúc, LazyRow chỉ tạo các phần tử hiển thị trong vùng nhìn thấy.
LazyRow hoạt động theo cùng nguyên tắc với LazyColumn, nhưng sắp xếp các phần tử theo chiều ngang. Khi cuộn trái hoặc phải, các phần tử ra khỏi vùng nhìn thấy được tái sử dụng để hiển thị phần tử mới. Điều này rất quan trọng cho thư viện ảnh có nhiều hình ảnh hoặc danh sách danh mục dài.
Theo Android Developers Blog, 2024, LazyRow sử dụng cùng kiến trúc LazyList như LazyColumn, bao gồm LazyListState, cơ chế tái sử dụng qua Pool và hỗ trợ các loại phần tử khác nhau. Hiệu quả tối đa đạt được với chiều cao phần tử cố định.
LazyRow chấp nhận các tham số modifier, state, contentPadding, reverseLayout, horizontalArrangement và verticalAlignment. Nội dung được định nghĩa qua các hàm DSL items và item, tương tự 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 quản lý sự phân bố các phần tử dọc theo trục ngang trong LazyRow. Các giá trị Arrangement tương tự như Row có sẵn: Start, Center, End, SpaceBetween, SpaceEvenly, SpaceAround và spacedBy với khoảng cách tùy chỉnh.
contentPadding thêm đệm ở các cạnh của vùng chứa LazyRow. Không giống như Modifier.padding, contentPadding được tính đến khi cuộn: phần tử đầu tiên sẽ có đệm từ cạnh trái, phần tử cuối cùng từ cạnh phải. Theo Material Design Guidelines, 2025, contentPadding là bắt buộc cho carousel và thư viện ảnh để phần tử đầu và cuối không dính vào mép màn hình.
verticalAlignment căn chỉnh các phần tử theo chiều dọc trong LazyRow. Mặc định sử dụng Alignment.Top. Để căn giữa các phần tử có chiều cao khác nhau, hãy sử dụng Alignment.CenterVertically, hữu ích cho carousel với ảnh có tỷ lệ khác nhau.
| Tham số | Mô tả | Giá trị mặc định |
|---|---|---|
| horizontalArrangement | Phân bố ngang các phần tử | Arrangement.Start |
| contentPadding | Đệm ở các cạnh vùng chứa | PaddingValues(0.dp) |
| verticalAlignment | Căn chỉnh dọc | Alignment.Top |
| reverseLayout | Thứ tự phần tử đảo ngược | false |
| userScrollEnabled | Bật cuộn người dùng | true |
LazyListState cho LazyRow hoạt động giống hệt LazyColumn: nó theo dõi phần tử hiển thị đầu tiên, độ lệch và vị trí cuộn tổng thể. Trạng thái được tạo qua rememberLazyListState() và truyền vào tham số state.
Điều khiển cuộn lập trình của LazyRow được thực hiện bằng các phương thức tương tự: animateScrollToItem cho hoạt ảnh mượt và scrollToItem cho cuộn tức thì. Cả hai được gọi bên trong một coroutine. Điều này hữu ích cho carousel có nút sang trái/phải hoặc cuộn tự động.
Theo Android Developers, 2024, LazyRow cũng hỗ trợ SnapFlingBehavior — hành vi cuộn nhanh dừng ở phần tử gần nhất thay vì giữa các phần tử. Điều này tạo hiệu ứng bám dính quen thuộc cho carousel và thư viện ảnh.
@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("Để bắt đầu") }
}
}
}
Ví dụ đầu tiên — LazyRow cho thư viện ảnh với xem trước. Mỗi phần tử là một Box với hình ảnh và chú thích. LazyRow xử lý hiệu quả hàng chục và hàng trăm ảnh, chỉ tải những ảnh hiển thị.
@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)
)
}
}
}
Ví dụ thứ hai — LazyRow cho danh sách danh mục với biểu tượng. Các danh mục được hiển thị dưới dạng chip và người dùng có thể cuộn ngang chúng. LazyRow với spacedBy và contentPadding tạo khoảng cách giữa các danh mục và ở các cạnh.
@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) }
)
}
}
}
Sự lựa chọn giữa LazyRow và Row phụ thuộc vào số lượng phần tử. Row phù hợp cho 5–10 phần tử luôn hiển thị trên màn hình. LazyRow cần thiết khi có nhiều phần tử hoặc số lượng của chúng là động.
Row render tất cả các phần tử cùng lúc, gây chậm trễ với số lượng lớn phần tử. LazyRow chỉ render các phần tử hiển thị, làm nó được ưa chuộng cho danh sách có thể cuộn. Theo Android Developers Blog, 2024, ngưỡng là khoảng 10 phần tử: nếu có nhiều phần tử hơn, hãy sử dụng LazyRow.
LazyRow cũng hỗ trợ hoạt ảnh, SnapFlingBehavior và nhóm qua dấu phân cách, làm nó linh hoạt hơn cho giao diện phức tạp. Row đơn giản hơn và không yêu cầu LazyListState, nhưng không được tối ưu cho danh sách dài.
Câu hỏi thường gặp
LazyRow cuộn ngang và sắp xếp các phần tử từ trái sang phải, trong khi LazyColumn cuộn dọc từ trên xuống dưới. Cả hai đều sử dụng cùng nguyên tắc tải chậm, LazyListState và hàm DSL items.
Truyền SnapFlingBehavior(listState) vào tham số flingBehavior của LazyRow. SnapFlingBehavior buộc LazyRow dừng ở phần tử gần nhất thay vì giữa các phần tử, tạo hiệu ứng bám dính cho carousel.
Theo dõi phần tử hiển thị cuối cùng qua LazyListState.layoutInfo và tải dữ liệu mới khi phần tử cuối cùng đến gần cuối danh sách. Cho cuộn vòng tròn, sử dụng triển khai tùy chỉnh với nhân bản phần tử.
Có, LazyRow có thể được lồng bên trong LazyColumn. Đây là mẫu tiêu chuẩn để tạo trang phức tạp với carousel ngang bên trong danh sách dọc. Mỗi LazyRow phải có chiều cao cố định để hoạt động chính xác.
Sử dụng LazyListState.layoutInfo.visibleItemsInfo và so sánh chỉ mục của phần tử hiển thị cuối cùng với tổng số trừ một. Khi các giá trị này khớp, LazyRow ở cuối danh sách.
Tóm tắt
Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay
IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.
Đọc thêm