What Is the Equivalent of [Nestedscrollview + Recyclerview] or [Nested Recyclerview (Recycler Inside Another Recycler) in Jetpack Compose

What is the equivalent of [NestedScrollView + RecyclerView] or [Nested RecyclerView (Recycler inside another recycler) in Jetpack compose

I think the best option, would be if the LazyVerticalGrid allows some sort of expand logic on each item, but looks like it's not supported yet (beta-03).

So I'm leaving here my solution using one single LazyColumn for the entire list and LazyRow for "My Books" section.

LazyColumn(
modifier = Modifier.fillMaxSize(),
) {
// My Books section
item {
Column(modifier = Modifier.fillMaxWidth()) {
Text("My Books")
LazyRow {
items(books) { item ->
// Each Item
}
}
}

}
// Whishlisted Books title
item {
Text("Whishlisted Books", style = MaterialTheme.typography.h4)
}
// Turning the list in a list of lists of two elements each
items(wishlisted.windowed(2, 2, true)) { item ->
Row {
// Draw item[0]
// Draw item[1]
}
}
}

Here is my gist with the full solution and the result is listed below.

Sample Image

LazyColumn inside Column with verticalScroll modifier throws exception

This happens when you wish to measure your LazyColumn with Constraints with Constraints.Infinity for the maxHeight which is not permitted as described in error log. There should be a fixed height or you shouldn't have another Scrollable with same orientation.

Column(
modifier = Modifier
// This is the cause
.verticalScroll(rememberScrollState())
) {
LazyColumn(
// and not having a Modifier that could return non-infinite max height contraint
modifier = Modifier
.fillMaxWidth()
) {

}

If you don't know exact height you can assign Modifier.weight(1f) to LazyColumn.

Contraints

This section is extra about `Constraints` and measurement you can skip this part if you are not interested in how it works.

What i mean by measuring with with Constraints.Infinity is when you create a Layout in Compose you use

Layout(modifier=modifier, content=content){
measurables: List<Measurable>, constraints: Constraints ->
}

You get child Composables as List<Measurable> which you can measure with Constraints provided by parent or the one you see fit by updating existing one with Constraints.copy or fixed one when you build a custom Composable with Layout.

val placeable = measurable.measure(constraints)

Constraints min/max width/height changes based on size modifier or scroll. When there is a scroll and you don't use any size modifier, Constraints return
minHeight =0, maxHeight= Int.MAX_VALUE as Constraints.Infinity

Modifier.fillMaxWidth()

Sample Image

Modifier.fillMaxWidth().weight(1f)

Sample Image

Easiest way to check Constraints with different Modifiers or with scroll is getting it from BoxWithConstraints

Itemdecoration in Jetpack compose

After your answer, this is what I understood...

@Composable
fun ListWithGradientBgScreen() {
val lazyListState = rememberLazyListState()
val firstVisibleIndex by remember {
derivedStateOf {
lazyListState.firstVisibleItemIndex
}
}
val totalVisibleItems by remember {
derivedStateOf {
lazyListState.layoutInfo.visibleItemsInfo.size
}
}
val itemsCount = 50
BoxWithConstraints(Modifier.fillMaxSize()) {
ListBg(firstVisibleIndex, totalVisibleItems, itemsCount, maxHeight)
LazyColumn(state = lazyListState, modifier = Modifier.fillMaxSize()) {
item {
Column(
Modifier
.fillMaxWidth()
.background(Color.White)
) {
Text(
text = "Some header",
style = MaterialTheme.typography.h5,
modifier = Modifier.padding(16.dp)
)
}
}

item {
Text(
text = "Some infinite list of things",
style = MaterialTheme.typography.h5,
modifier = Modifier.padding(16.dp)
)
}

items(itemsCount) {
Text(
text = "Item $it",
Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 6.dp)
.background(Color.LightGray)
.padding(8.dp)
)
}
}
}
}

and to change the background in according to the background, you can define something like the following:

@Composable
private fun ListBg(
firstVisibleIndex: Int,
totalVisibleItems: Int,
itemsCount: Int,
maxHeight: Dp
) {
val hasNoScroll = itemsCount <= totalVisibleItems
val totalHeight = if (hasNoScroll) maxHeight else maxHeight * 3
val scrollableBgHeight = if (hasNoScroll) maxHeight else totalHeight - maxHeight
val scrollStep = scrollableBgHeight / (itemsCount + 2 - totalVisibleItems)
val yOffset = if (hasNoScroll) 0.dp else -(scrollStep * firstVisibleIndex)
Box(
Modifier
.wrapContentHeight(unbounded = true, align = Alignment.Top)
.background(Color.Yellow)
.offset { IntOffset(x = 0, y = yOffset.roundToPx()) }
) {
Box(
modifier = Modifier
.fillMaxWidth()
.height(totalHeight)
.drawBehind {
drawRoundRect(
Brush.linearGradient(
0f to Color.Red,
0.6f to Color.DarkGray,
1.0f to Color.Green,
),
)
}
)
}
}

Here is the result:

Sample Image

Is there a way to nest a LazyVerticalGrid iniside a vertical scrollable view in Jetpack Compose

simple example:

ConstraintLayout(Modifier.verticalScroll(rememberScrollState())){
LazyVerticalGrid( cells = GridCells.Fixed(2),Modifier.height(150.dp)){
items(5){
Text(text = "hello")
}
}
}

When a list is nested, the internal list needs to be fixed in height



Related Topics



Leave a reply



Submit