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.
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()
Modifier.fillMaxWidth().weight(1f)
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:
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
Button in Custom Android Toast
Android Class Parcelable with Arraylist
Application Content Goes Behind the Navigation Bar in Android L
Opening Infowindow Automatically When Adding Marker Google Maps V2 Android
How to Get the Dreaded Write_Secure_Settings Permission for My Android App
Android Decoder->Decode Returned False for Bitmap Download
Android:Change Button Text and Background Color
Android: Custom Separator (Or Even Item) in Listview Depening on Content of Item
How to Use Getlistview() in Activity
How to Reduce the Spacing Between the Action Item Icons on Action Bar
Intent Putextra Arraylist<Namevaluepair>
Clear Application Cache on Exit in Android
Gcm Push Notification with ASP.NET
How to Load Class Androidcomponentsextension After Upgrading the Android Gradle Plugin 7.1