LazyColumn and LazyRow take a DSL block: item { } adds one entry, items(list) { } one per element, and the layout decides which to compose. BookNest's catalog puts a "Staff picks" strip above one BookRow per book:
LazyColumn(contentPadding = PaddingValues(16.dp), // inside the scroll, not a frame
verticalArrangement = Arrangement.spacedBy(8.dp)) {
item(contentType = "header") {
Text("Staff picks", style = MaterialTheme.typography.titleLarge)
LazyRow(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
items(picks, key = { it.id }) { Cover(it) }
}
}
items(books, key = { it.id }, contentType = { "book" }) { book ->
counter.composed++
BookRow(book)
}
}A key gives each row a stable identity, like keyExtractor in a FlatList (keyExtractor and renderItem); without one, inserting a book at the top would hand every row's remembered state to its neighbor. Keys must be unique and fit in a Bundle, since the scroll position is saved by key. A LazyRow inside a LazyColumn is fine; two nested lists scrolling the same way throw, because the inner one would get infinite height.