Is it a good practice to nest LazyColumns? Why I'm...
# compose
d
Is it a good practice to nest LazyColumns? Why I'm considering this: I have this layout: toolbar + composable + LazyColumn, and the thing is that items in that column need to be inside a bottomsheet-like Surface with white background and elevation (cast a shadow). See screenshot in the thread. And I need a nested scroll to eventually hide toolbar + composable.
Here's a concept screenshot, notice the shadow below bottom-sheet-like surface, currently that's laid out like this:
Copy code
Column {
  Toolbar()
  HeaderComposable()
  Surface {
    LazyColumn {
      item { SheetHandle() }
      items(bottomSheetItems) { ItemComposable() }
    }
  }
}
d
Nesting lazy column is bad practice for sure. Just use a single one and add all the items in it.
☝️ 1
n
why don't you use a BottomSheetScaffold to display the content of your bottom sheet ?
c
A lazy column essentially has infinite height which is why you can't have a lazy column inside of a lazy column.
d
1. I want to try to use a single one, but there's no way to add that sheet-like thing with elevation. those
Apple Inc
things are individual items. How would you do it? set elevation on each of those little items excluding a toolbar and the composable below? 2. BottomSheetScaffold won't work, because this is not an actual bottomwheet it's part of scrollable content, and everything above it slowly fades as it translates up. Designer vision 🙂
z
You should also check if you really need a LazyColumn. If all items fit the screen then you can’t recycle anyway.
d
It seems I really need it. There can be thousands of these items on the bottom
n
you can still fight the designer 🥊 I think you can still use the bottomsheetscaffold as you can react to sheet movement (which would allows to translate + fade the content ?) and how I usually handle those situation -> I explain to the designer that I'm tied to the component the system provide me, as designing a screen with custom component is completely possible, but it can multiply times you pass making the screen double, triple or worse
here we can definitelly see a Material BottomSheet so... you can definitelly but a lazycolumn in it and it will scroll as wanted
d
Yeah, I can fight them, but for now I have time to play a bit, so that's what I'm trying 🙂
👍 1
Thanks, will try to take that route too
z
You can certainly nest scrollables that scroll on the same axis, and that’s a valid way to implement collapsing toolbars. Compose provides a pretty powerful api for handling nested scroll events. You can also nest lazy scrollables that scroll on different axes, eg
LazyRow
inside
LazyColumn
items. What’s bad is to nest lazy scrollables on the same axis, because only the outer one will actually be lazy. The reason is that the outer one measures its items without bounds on the scroll dimension, which means the inner one will always measure to its full height and never actually “use” laziness.
d
I see, thanks!
a
Pretty easy to do using
Modifier.nestedScroll()
I think.
d
I tried that but didn't yet figure out how to expand Surface height while LazyColumn inside it scrolls (see layout scheme above)
a
You don't need to change the height. The surface's height should always be the max height. Basically you set the nested scroll modifier on the surface's parent, and on pre scroll, consume scroll delta and offset the surface.
d
oh. I will try that, thank you
Tried this and the difficulty is how to calculate initial Surface offset. I've put everything in a Box (to let the Surface occupy max height), but initially it must be placed under the toolbar and header.
a
A simple custom layout should work.
d
Thought about this too, trying to write one 🙂
a
Wrote a quick sample.
n
btw I just looked how to do it when it's not a "first"/"last" item you want, you can use : Modifier.layoutId(layoutId: Any) and then
val iconPlaceable = measurables.first { it.layoutId == "icon" }.measure(constraints)
(found in JetSnack sample)
d
Wrote a quick sample.
Great, thank you! I ended up with something like this, but my version doesn't do flings properly. Yours has the fling not working until the surface is fully expanded, but then it works. I tried to look how bottom sheet scaffold does it's flings and it uses SwipableState + modifier, and all this starts to overwhelm me 🙂 Need to rest.
btw I just looked how to do it when it's not a "first"/"last" item you want
Niice, didn't know about this trick!
a
Note that for fling to work properly before the surface is fully expanded, you need this bug fix which will likely land in the next beta release.
d
wow, that's great, thanks!