What can I do if I need to put a `lazycolumn` insi...
# compose
p
What can I do if I need to put a
lazycolumn
inside a
lazycolumn
? I'm getting this error: > IllegalStateException: Vertically scrollable component was measured with an infinity maximum height constraints, which is disallowed. I know that as doc says (https://developer.android.com/develop/ui/compose/lists#avoid-nesting-scrollable), we must avoid nesting components scrollable in the same direction. But my app is an special app, like an "app constructor" in which the user can construct an app using different types of items, for example: texts, images, vertical scroll containers (
lazycolumns
), horizontal scroll containers (
lazyrows
), etc and for example, the user is free to put a vertical scroll, with some text and an horizontall scroll, and that horizontal scroll can have a verticall scroll inside. I need to know how to achieve this
s
p
please see my updated text, I know that as doc says, we must
avoid nesting components scrollable in the same direction
but my app is an "app constructor" in which the user can construct an app using texts, images, vertical scroll containers (lazycolumns), etc and he can put a vertical scroll, with some text and an horizontall scroll, with a verticall scroll inside for example. I need to know how to achieve this (editado
s
You can’t directly nest LazyColumns if they scroll in the same direction; that’s just how lazy scrolling containers work. Instead, it’s better to add different item types within a single LazyColumn/Row/Grid/etc. For example, if you’ve got a category of items that would normally go in its own vertical list, just add each item as an entry in your main LazyColumn. And honestly, LazyColumns in Compose are just as powerful as RecyclerView for building flexible, scrollable UIs. If you’re working with screens that have mixed content, it really helps to think in terms of distinct item types. It’s a pattern from the RecyclerView days that keeps things organized and way easier to maintain. Here are a couple of links, 1, 2 to give you a better idea of how it should work. Definitely avoid hacky workarounds to nest scrolling lists in the same direction, it’s just not worth the trouble.
p
Well maybe I didn't explain myself correctly
this is not a custom app in which I can decide how many items put in the main lazycolumn. This is an app constructor in which I have verticall scroll element, and the user who construct the app, can nest elements, so I can't figure out which app will build the user. I need to allow it
s
Yeah exactly! We’re on the same page here, it all comes down to making a UI builder. The whole idea of building complex scrolling lists isn’t new at all! Like, Airbnb’s Epoxy library was doing this with RecyclerView way back - they even built entire screens this way. With Compose, it’s basically the same concept but easier. Just think of your screen as a bunch of different sections put together - each section can be whatever you want (grid, carousel, list, etc). It’s like building with legos - you just snap different pieces together to make your screen.
p
but then, how can I nest a lazycolumn inside a lazyrow which is inside a lazycolumn without getting that error?
s
I need to allow it
So how do you expect it to work if you try to include a lazy list within another lazy list? What kind of UX are you aiming for with that setup?
p
well, I don't know, the user is who will decide
s
When you try to nest a LazyColumn inside another LazyColumn (both scrolling vertically), Compose runs into an “infinite height” issue. Each one expects a defined height, but the inner layout ends up needing infinite space, which causes errors. Lazy layouts only load items that fit the visible area to save memory, so they rely on knowing their container’s size. But if you nest them with different scroll directions, like a LazyColumn inside a LazyRow, it works fine because each one has clear boundaries in one dimension, avoiding the infinite size problem!
p
In this case I disscovered the problem simply doing this simple app with the app constructor: putting a row (lazyrow) in my main container (lazycolumn). That row has two items, each one can have multiple items, so each item is a lazycolumn. There you have it. A lazycolumn inside a lazyrow, inside a lazycolumn
s
Does the nested layout need to be lazy, or can it just be a regular layout? Like a scrollable layout with items?
p
It needs to be scrollable, because the user can put infinite amount of items inside
I use lazycolumn just because it's the recommended way when can receive infinite items
but if I migrate to column, the problem persist, because I need scrollable
this was perfectly possible under android view system
must be possible in compose
s
I’m sorry, but it might be helpful to take a step back and revisit this concept, as it doesn’t seem quite right from my perspective. Embedding lazy scrolling lists inside each other with the same direction just doesn’t seem right by itself. That’s not how they’re designed to work.
p
so is not possible in compose? my app is simply not possible to migrate to compose then?
s
this was perfectly possible under android view system
No, it wasn’t. RecyclerView doesn’t throw an error when you nest one inside another. Instead, the embedded RecyclerView simply stops recycling items and behaves like a regular, non-lazy layout, keeping all its items in memory. That’s how it was designed. It doesn’t crash, but it’s no longer lazy either.
p
I didn't used recycler view in the view system version, I just used linearlayouts with scroll
I can confirm you that It works, nesting scrolls was not a problem in view system
s
If you weren’t using RecyclerViews, then you wouldn’t need to use them here either. You could just use regular Rows and Columns with scroll modifiers and the nested scroll connection modifier.
Copy code
<https://developer.android.com/develop/ui/compose/touch-input/pointer-input/scroll#nested-scrolling>
Compose supports as well.
p
mmm
I think not
I read that column with scroll has the same exception
s
read the doc I sent, everything works
p
I'll try it, but then, if it works, it's a possible solution, but then, I will lose the benefits of lazy loading
😞
s
I will lose the benefits of lazy loading
If you’re already nesting lazy lists that scroll in the same direction, you’re effectively losing the lazy behavior, because that’s not how it’s designed to work. This isn’t how it worked with RecyclerView either.
p
well I wanted to improve the compose version respect the view version
but it seems for this case will not be possible
well, at least will work
😕
s
Yeah, it’s a bit of a wrong concept. But I’m not here to judge, and I can’t. I’ve shared my perspective, and you can either take it into consideration or proceed in your own way. That’s all.
p
well, In this case the concept can't be changed, because is not a normal application
it's an abstract meta application in which the user will construct the application
if the user decides to nest scrolls, is his decission
I'm forced to use columns instead of lazy columns not by a wrong concept but by a requisite of the app constructor
s
Once again, you’re focusing too much on the high-level user concepts, which is how your task is framed, making something scrollable and embeddable. However, the actual implementation and your code should consider platform-specific details. Don’t get caught up in the tunnel vision of the task description as the only implementation way. A lot of people have already tried to assist you. Everything is possible, just try to look from different angle.
p
yep, that whould be the best option, but it's a requisite. I mean... looking it from a different angle, I whould apply the limitation to the user, not letting him doing that
but I can't, because I need to port this application without lossing anything of the current requisites
s
I’m not talking about restricting anything for the user. Alright, we’re venturing into more abstract territory now, and it’s getting a bit away from Compose, so I’ll step back. 👍
p
XD
ok, thanks Serhii Y.
I'm sorry I didn't understand what you propose to achieve this without lossing the lazycolumn benefits, but at least now I know how to make it work and that's a start. I appreciate your help. Thank you
well, finally I get it working! simply adding this modifier to the lazycolumns... it works
Copy code
.heightIn(max = Short.MAX_VALUE.toInt().dp)
👾 1
probably Short.MAX_VALUE is a low value and I must add more? or a lazycolumn with 999999 items will not have a enormous height? maybe reusing the items the heigh is not super big?
s
The docs link I posted do cover the fact that you can nest scrollable contents if you give them fixed sizes on the axis in which they are scrolling. It's all in the same one link I gave you twice before https://developer.android.com/develop/ui/compose/lists#avoid-nesting-scrollable "As well as cases where you still use the same direction layouts, but also set a fixed size to the nested children:"
Copy code
Column(
    modifier = Modifier.verticalScroll(scrollState)
) {
    LazyColumn(
        modifier = Modifier.height(200.dp)
    ) {
        // ...
    }
}
But reading what you want to achieve, this does not look to be what you actually want to do here 😄 Did you test this and does it actually behave how you wish it to, besides it just not crashing?
p
yes it seems to work, the difference with your propossal is that .height(200.dp) gives a fixed height to the lazycolumn, but .heightIn(max = Short.MAX_VALUE.toInt().dp) doesn't do that, instead, it gives the maximum height I can have. I mean... with your approach will have always 200.dp even when the content needs only 10.dp. With the second approach will have just the content .dp but more if necessary
the problem is that .heightIn(max = Short.MAX_VALUE.toInt().dp) seems to be low when the lazycolumn can have thousands of items... in that case maybe I need to put a greater value, maybe Int.MAX_VALUE
what do you think?
s
If it would have thousands items at this conditions app simply crash
p
a lazycolumn doesn't support to manage 2k or 3k items?
s
by doing this, you’ve essentially disabled all of the lazy behavior, which makes me think you’re not aware of how lazy layouts actually work. I’d really recommend reading up on the fundamentals of lazy layouts—it’s crucial information that will help clarify things for you.
Lazy lists aren’t magic; they can’t handle thousands of items effortlessly. They work within certain constraints. To handle thousands of items effectively, lazy lists only lay out the items that are visible within the bounds. The rest remain unlaid out and are composed lazily as you scroll. Lazy lists reuse the cells that were already on screen, simply moving them to the position of each new item as it’s composed during scrolling.
p
are you sure that lazy behaviour is disabled if you set the heightin property?
s
If you set the bounds to be extremely large, all items will effectively fit within those bounds. It’s not just about heightIn or widthIn modifiers; if the bounds are large enough to contain the entire lazy list content, the list won’t reuse items because everything is already within view. Hope that clears it up!
We’ve been trying to convey, over a few messages now, that this approach might not be the best fit for what you’re trying to accomplish. Just to reiterate, in this case, there won’t be any item reuse, which is both inefficient and not how lazy lists are designed to work. This approach wouldn’t work effectively with RecyclerView either. We’re just making this point clear again.
1