LazyRow — 是 Jetpack Compose 中的一个 composable 函数,用于创建具有懒加载元素的水平列表。与 Row 不同,LazyRow 仅创建可见元素,并在水平滚动时重复使用它们。根据 Google Android Documentation, 2025,LazyRow 是 LazyColumn 的水平对应组件,适用于移动应用程序中的轮播、图库和水平菜单。
要点
LazyRow — 是一个 composable 函数,实现了具有懒加载元素的水平可滚动列表。与同时渲染所有子元素的 Row 不同,LazyRow 仅创建在可视区域内可见的元素。
LazyRow 的工作原理与 LazyColumn 相同,但将元素水平排列。向左或向右滚动时,离开可视区域的元素会被重复用于显示新元素。这对于包含大量图片的图库或长分类列表至关重要。
根据 Android Developers Blog, 2024,LazyRow 使用与 LazyColumn 相同的 LazyList 架构,包括 LazyListState、通过 Pool 的复用机制以及对不同元素类型的支持。使用固定元素高度可实现最高效率。
LazyRow 接受 modifier、state、contentPadding、reverseLayout、horizontalArrangement 和 verticalAlignment 参数。内容通过 DSL 函数 items 和 item 定义,类似于 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 管理 LazyRow 内部元素沿水平轴的分布。与 Row 中相同的 Arrangement 值都可用:Start、Center、End、SpaceBetween、SpaceEvenly、SpaceAround 以及带有自定义间距的 spacedBy。
contentPadding 在 LazyRow 容器边缘添加内边距。与 Modifier.padding 不同,contentPadding 在滚动时会被考虑:第一个元素将距离左边缘有间距,最后一个元素距离右边缘。根据 Material Design Guidelines, 2025,对于轮播和图库,contentPadding 是必需的,以确保第一个和最后一个元素不会紧贴屏幕边缘。
verticalAlignment 在 LazyRow 内部垂直对齐元素。默认使用 Alignment.Top。要居中对齐不同高度的元素,请使用 Alignment.CenterVertically,这对于包含不同比例图片的轮播非常有用。
| 参数 | 描述 | 默认值 |
|---|---|---|
| horizontalArrangement | 元素水平分布 | Arrangement.Start |
| contentPadding | 容器边缘内边距 | PaddingValues(0.dp) |
| verticalAlignment | 垂直对齐 | Alignment.Top |
| reverseLayout | 元素反向顺序 | false |
| userScrollEnabled | 允许用户滚动 | true |
LazyListState 在 LazyRow 中的工作方式与 LazyColumn 完全相同:跟踪第一个可见元素、偏移量和整体滚动位置。状态通过 rememberLazyListState() 创建,并传递给 state 参数。
LazyRow 的程序化滚动控制通过相同的方法完成:animateScrollToItem 用于平滑动画,scrollToItem 用于即时滚动。两者都在协程内调用。这对于带有“左/右”按钮的轮播或自动滚动非常有用。
根据 Android Developers, 2024,LazyRow 还支持 SnapFlingBehavior — 快速滚动时的行为,它会停在最近的元素上,而不是停在元素之间。这创建了一种“粘附”到元素的效果,在轮播和图库中很常见。
@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("开始使用") }
}
}
}
第一个示例 — 用于带预览的图片图库的 LazyRow。每个元素是一个包含图片和标题的 Box。LazyRow 高效处理数十和数百张图片,仅加载可见的图片。
@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)
)
}
}
}
第二个示例 — 用于带图标的分类列表的 LazyRow。分类以芯片形式显示,用户可以水平滚动它们。使用 spacedBy 和 contentPadding 的 LazyRow 在分类之间和边缘创建间距。
@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) }
)
}
}
}
在 LazyRow 和 Row 之间的选择取决于元素的数量。Row 适用于 5–10 个始终在屏幕上可见的元素。当元素很多或其数量动态变化时,必须使用 LazyRow。
Row 同时渲染所有元素,这在元素数量较多时会导致延迟。LazyRow 仅渲染可见元素,使其成为可滚动列表的首选。根据 Android Developers Blog, 2024,过渡阈值约为 10 个元素:如果更多,请使用 LazyRow。
LazyRow 还支持动画、SnapFlingBehavior 和通过分隔符进行分组,使其对于复杂界面更加灵活。Row 更简单且不需要 LazyListState,但未针对长列表进行优化。
常见问题解答
LazyRow 水平滚动并将元素从左到右排列,而 LazyColumn 垂直从上到下滚动。两者使用相同的懒加载原则、LazyListState 和 DSL items 函数。
将 SnapFlingBehavior(listState) 传递给 LazyRow 的 flingBehavior 参数。SnapFlingBehaviour 使 LazyRow 停在最近的元素上,而不是停在元素之间,为轮播创建粘附效果。
通过 LazyListState.layoutInfo 跟踪最后一个可见元素,当最后一个元素接近列表末尾时加载新数据。对于循环滚动,使用带有元素重复的自定义实现。
是的,LazyRow 可以嵌套在 LazyColumn 中。这是在垂直列表内创建带有水平轮播的复杂页面的标准模式。每个 LazyRow 应有固定高度以确保正常工作。
使用 LazyListState.layoutInfo.visibleItemsInfo 将最后一个可见元素的索引与总数减一进行比较。当这些值匹配时,LazyRow 位于列表末尾。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。