Noah
Noah

Reputation: 3435

Use item keys in non-lazy Column

LazyColumn has item keys, in order to tie the item's state to a unique identifier rather than the list index. Is there a way to use item keys in a non-lazy list like this one?

Column {
  for (item in list) {
    Text(item)
  }
}

The reason I ask is because I want to implement SwipeToDismiss to delete items from a list, which only works if you pass a key to a LazyColumn (solution), but my list of dismissable items is nested inside of a LazyColumn, and I can't nest a LazyColumn inside of another LazyColumn's itemContent block (Nesting scrollable in the same direction layouts is not allowed):

val items = listOf<String>(...)
val groups = items.groupBy { it.first() }

LazyColumn {
  items(groups, { /* key */ }) { (firstChar, group) ->
    // not allowed!
    LazyColumn {
      items(group, { /* key */ }) { item ->
        Text(item)
      }
    }
  }
}

I could wrap the items() call itself in a for loop like this:

val items = listOf<String>(...)
val groups = items.groupBy { it.first() }

LazyColumn {
  groups.forEach { (firstChar, group) ->
    items(group, { /* key */ }) { item ->
      Text(item)
    }
  }
}

But then state in each of the outer loop's items would be keyed against its index. And I need to provide item keys for groups as well, in order to preserve their state on position changes.

Upvotes: 11

Views: 6754

Answers (1)

chuckj
chuckj

Reputation: 29575

The general pattern for this is,

for (item in items) {
  key(item) {
    ... // use item
  }
}

The key composable is special and Compose will use item as a key to detect when the state should move when an the value of item moves in the items collection.

Upvotes: 19

Related Questions