Suppose I have the following composable ```@Compos...
# compose
u
Suppose I have the following composable
Copy code
@Composable
fun MySectionedLazyList(viewModel: SectionedListViewModel) {
    LazyColumn(modifier = Modifier.fillMaxSize()) {
        viewModel.section1?.let {
            items(items = it.items, key ={it.key}) {
                Item1(it.data)
            }
        }
        viewModel.section2?.let {
            items(items = it.items, key ={it.key}) {
                Item2(it.data)
            }
        }
        viewModel.section3?.let {
            items(items = it.items, key ={it.key}) {
                Item3(it.data)
            }
        }
    }
}
and I would like to scroll to the 5th item in
section3
, but I don’t know it’s index, only it’s key, how would I accomplish such a task? Everything I’m seeing requires use of the item index, which while I could compute, it would be much easier if there was a way to scroll to an item with a specific key rather than just based off index. Is this just functionality that I’d have to implement myself?
or, is the real answer to combine everything to be displayed into a single list instead? That doesn’t seem ideal because then I’ve got to build in logic at the view level to determining which composable the data is supposed to get passed to (multiple dispatch would kinda eliminate that need, but is not something that Kotlin currently supports, and likely never will)
u
I literally just made that issue a few minutes ago.
e
haha, I see
well, the closest workaround I can think of is to wrap
LazyListScope
with your own that tracks the keys/indices
u
Yup, that is what I thought of as well, this original problem was actually brought up by a coworker 6 months ago and I proposed the same solution then as well, but had forgotten about that until I ran into the issue today and the coworker brought it up that we had previously discussed that very solution. At the time it was deemed to be too much effort and didn’t provide enough value to be worth the development time, but maybe now that is different.
e
untested but perhaps
Copy code
fun LazyListScope.logKeys(content: LazyListScope.() -> Unit): List<Any> = buildList {
    object : LazyListScope by this@logKeys {
        override fun item(key: Any?, contentType: Any?, content: @Composable (LazyItemScope.() -> Unit)) {
            this@buildList.add(key ?: this@buildList.size)
            this@logKeys.item(key, contentType, content)
        }

        override fun items(
            count: Int,
            key: ((index: Int) -> Any)?,
            contentType: (index: Int) -> Any?,
            itemContent: @Composable (LazyItemScope.(index: Int) -> Unit)
        ) {
            this@buildList.addAll(List(count) { key?.invoke(it) ?: (this@buildList.size + it) })
            this@logKeys.items(count, key, contentType, itemContent)
        }
    }.content()
}
Copy code
var keys by remember { mutableStateOf(emptyList<Any>()) }
val state = rememberLazyListState()
LazyColumn(state = state) {
    keys = logKeys {
        items(...)
    }
}
Copy code
state.scrollToItem(keys.indexOf(key))
d
is the real answer to combine everything to be displayed into a single list instead?
I suggest doing this. I did this on a project I am working on and it’s reliable.
Representing every item in the list as it’s own item allows for doing interesting things too. Like scrolling to a specific divider for example. Or even a specific item in a specific section or a specific section.
It’s flexible at the cost of some infrastructure.
Like most flexible things.
You could add support later for the indicator like Slack has too!
u
@dewildte so I take it then in your composable you have a
when
block that is in charge of dispatching to the correct composable for each item in the list? I’d prefer to keep the logic out of the view, but I’d also like to keep the view out of the data class, and I think both of those things are at odds with each other. Which comes back to my previous comment about wishing Kotlin supported multiple dispatch as then the logic is handled by the language rules.