https://kotlinlang.org logo
#compose
Title
# compose
j

Jorge Domínguez

05/10/2022, 7:51 PM
Is it possible to animate changes between two inputs of a
LazyColumn
?
Copy code
LazyColumn {
    tasksList.forEach { task ->
        item {
            TaskItem(
                taskName = task.name,
                onStartTask = { onStartTask(task) }
            )
        }
    }
}
I'd like to animate a
TaskItem
if the corresponding
Task
object is not present in the next
tasksList
passed to
LazyColumn
o

Oleksandr Balan

05/10/2022, 7:58 PM
Firstly, each item must have a unique key, so that Compose could keep track on them and animate accordingly. Do your
task
has some identifier which you can use for the key?
Copy code
item(key = ...) {
    TaskItem(...)
}
Secondly, you must add an
animateItemPlacement
Modifier to each item, like this:
Copy code
item(key = ...) {
    TaskItem(
        modifier = Modifier.animateItemPlacement()
    )
}
j

Jorge Domínguez

05/10/2022, 8:09 PM
According to the
animateItemPlacement()
docs it only animates order changes. Is it possible to animate a visibility change? so that if the item is not present in the new
tasksList
then the "disappearance" of the item can be animated
o

Oleksandr Balan

05/10/2022, 8:31 PM
I am not sure which effect do you want to achieve, but in my case it looks “okish” 🤷
j

Jorge Domínguez

05/10/2022, 8:39 PM
I want to achieve pretty much the same as what your video shows, so I must be missing something then
o

Oleksandr Balan

05/11/2022, 6:13 AM
I have it really simple:
Copy code
val items = remember { mutableStateListOf(*List(100) { it }.toTypedArray()) }
LazyColumn(
    contentPadding = PaddingValues(SpacingMedium),
    verticalArrangement = Arrangement.spacedBy(SpacingMedium),
    modifier = Modifier.fillMaxSize()
) {

    items(items, key = { it }) {
        Item(
            id = it,
            onRemove = { items.remove(it) },
            modifier = Modifier
                .fillMaxWidth()
                .animateItemPlacement()
        )
    }
}
🙌 1
j

Jorge Domínguez

05/11/2022, 2:18 PM
oh I see, you're just removing the item from the list. I assume that in my case it doesn't work because when I remove an item I'm actually updating a Room database that returns a new list which is then passed to LazyColumn, so there might be some kind of issue with the IDs. I believe this is a work in progress as specified here, but thanks anyway for your guidance 🤝.
o

Oleksandr Balan

05/11/2022, 2:28 PM
Hm, actually it should also work this way, where
onRemove
creates a new list and sets to the State property:
Copy code
var items by remember { mutableStateOf(List(100) { it }) }
LazyColumn(
    contentPadding = PaddingValues(SpacingMedium),
    verticalArrangement = Arrangement.spacedBy(SpacingMedium),
    modifier = Modifier.fillMaxSize()
) {
    items(items, key = { it }) {
        Item(
            id = it,
            onRemove = { items = items.toMutableList().apply { remove(it) } },
            modifier = Modifier
                .fillMaxWidth()
                .animateItemPlacement()
        )
    }
}
But yeah, keys should be unique and remain same after change. Alternatively you may use
.hashCode()
for your key 🤔
j

Jorge Domínguez

05/11/2022, 2:31 PM
As soon as I get the chance I'll check with
.hashCode()
as key, since currently I'm using the primary key field of the Room entity, though it should work the same...
11 Views