https://kotlinlang.org logo
Title
t

Thomas

12/01/2020, 12:56 PM
Could someone please hint on how to build a list that allows multiple selection of items? Here is what I have so far:
@Composable
fun ThirdRow(currentPos: Int, checksums: List<String>) {
    val items = if (checksums.isNotEmpty())
        df.getFiles(checksums[currentPos]) else emptyList()
    LazyColumnFor(items,
            modifier = Modifier.fillMaxSize().padding(8.dp),
            itemContent = { item ->
                ListItem(text = { Text(item.parent) },
                        secondaryText = { Text(item.name) })
            })
}
j

jim

12/01/2020, 1:29 PM
@Composable
fun ThirdRow(currentPos: Int, checksums: List<String>, selected: Set<String>, onSelectionToggled: (String)->Unit) {
    val items = if (checksums.isNotEmpty())
        df.getFiles(checksums[currentPos]) else emptyList()
    LazyColumnFor(items,
            modifier = Modifier.fillMaxSize().padding(8.dp),
            itemContent = { item ->
                if(selected.contains(item.checksum)) { ... }
                else { ... }
                // TODO: Add a click handler that will invoke onSelectionToggled(item.checksum) when selection is toggled.
                ListItem(text = { Text(item.parent) },
                        secondaryText = { Text(item.name) })
            })
}
👍 1
d

Dominaezzz

12/01/2020, 1:45 PM
Modifier.toggleable(...)
👍 1
t

Thomas

12/01/2020, 4:47 PM
Thanks for answering. Now I do this one:
@Composable
fun ThirdRow(currentPos: Int, checksums: List<String>, selected: SnapshotStateMap<Int, Boolean>) {
    val items = if (checksums.isNotEmpty())
        df.getFiles(checksums[currentPos]) else emptyList()
    LazyColumnForIndexed(items,
            modifier = Modifier.fillMaxSize().padding(8.dp),
            itemContent = { index, item ->
                val current = selected[index] ?: false
                ListItem(secondaryText = { Text(item.parent) },
                        modifier = Modifier.toggleable(onValueChange = {
                            selected[index] = !current
                        },
                                value = current)
                                .background(if (current)
                                    Color.LightGray else Color.Transparent),
                        text = { Text(item.name) })
            })
}
Works great. But still pondering if there isn't more builtin support in Compose... Again, thank you very much for helping with this one...
d

Dominaezzz

12/01/2020, 4:50 PM
What do you mean by more built in?
Modifier.toggleable(...)
is built in.
👍 1
j

jim

12/01/2020, 4:56 PM
I think he is looking for a built-in multi-select column widget. Under this assumption, no, I don't think there is anything more built-in, but the solution here is just a few lines of code. Often, generalized solutions to problems like this end up adding more cognitive overhead to learn+use than to just re-implementing when needed, but if you create a generalization of this that you think would be useful to other people, feel free to share on github or maven.
👍 2
t

Thomas

12/01/2020, 7:05 PM
To explain, I am afraid I still am way too influenced by imperative UI frameworks. 😀 Consider Swing, there is ListSelectionModel and stuff like that, I need to leave this behind. 😀 Thanks for helping me sorting this out.