How can I create an expandable list of items? Ther...
# compose
m
How can I create an expandable list of items? There are people claiming to do it, but all of them I've found are in fact lists of expandable items, which isn't the same. I want, for example, to show a list of categories and clicking on a category expands it to show its sub-categories (while still showing the categories). It seems to me that the restriction of no nested same-direction composables makes this quite hard to do. I can make up a workaround, but it's very tedious by comparison.
s
It’d help if you showed in a screenshot or something like that about what you mean here.
m
Here y'go. Clicking on a downarrow on the right expands the section showing its sub items, the "E-Riders" section has been expanded.
s
Aha, then it looks like you can add more items to the original list then, which can be of a different type or have some sort of variable so that the list knows to render them slightly different than the rest of the items. And for how they come into the view, you'd want some animation to play I suppose, that can even be part of the item itself, starts from height of 0dp and animates to the final height
m
Yes, that's the workaround that I thought of. Not great by comparison 😕
s
By comparison to what? What would you prefer this to look like? You can also make that expandable content all be inside a
Column {}
so it’s the same as just adding 1 item to the big list. Just while making sure that it by itself isn’t also scrollable and therefore would try to take up an infinite height.
m
Ah! That is the piece I was missing. I did put the expandable content inside a column but it crashed, but it's because it was scrollable! Ok, thanks. It's the restriction on nested scrollables that was stopping me, and now I see I can just remove the "scrollable" part.
s
Yep, your content will by default be scrollable since you’ll be scrolling the outer parent. No need for an inner scrollable content too. This restriction is there for a good reason, and often you can realize that you didn’t even need this nested scrolling situation in the first place. I hope this does it for you! 😊
d
I built something like this and can explain how it works. First we need to group the items by their header into a map. Like
Map<CategoryItem, List<ListItem>>
for example. Next, represent each item in the list as a separate
LazyListScope.item
, including the
CategoryItem
item. Wrap each individual item in the list that is not a category in the
AnimatedVisibility
Composable. When the user clicks on the chevron then iterate over all the items in that category and update their visibility to false. Something like this:
Copy code
onClick = { categories[categoryItem]?.forEach { item -> item.isVisible = false } }
Each individual item under the category item will dissapear. Instead of a
Map
you could use a custom data structure too. There are some advantages to doing it this way for instance: • Being able to display the categories as
stickyHeader
s • Being able to dynamically scroll to any item in the list ◦ This is not possible if the items below the category is a big
Column
. ◦ Being able to selectively show or hide an item in the category even when it is expanded.
Here’s an example UI I built that does what I am talking about:
Change the
enter
and
exit
specs in the
AnimatedVisibility
to
expandIn
and
shrinkOut
respectively.
m
Thank you both, these really nudged me in the right direction!