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

Chuck Stein

07/26/2022, 7:45 PM
I understand that animating insertions/deletions into a
LazyList
is still under development, but what's the recommendation for animating insertions/deletions into a regular
Column
or
Row
?
My use case is I have a list of items which I get from the ViewModel's view state, and you can add/remove these items from the UI, and the
Column
these items live in cannot be a
LazyColumn
because much higher up in the compose tree there is already a
LazyColumn
container (and a
LazyColumn
within another
LazyColumn
causes an error).
j

Joseph Hawkes-Cates

07/26/2022, 7:52 PM
AnimatedVisibility has extensions on RowScope and ColumnScope that should work
c

Chuck Stein

07/26/2022, 8:10 PM
Even with the
ColumnScope
extension, it doesn't work if my items are coming from the view state, because if an item is removed from the
items
list, when I iterate over the list on the next composition, I won't even reach the
AnimatedVisibility
that was previously wrapping that
item
, because it's no longer in the list I'm iterating over. So the items don't animate even with the following code:
Copy code
items.forEach { item ->
    AnimatedVisibility(visible = item in items) {
        MyItemImpl(item)
    }
}
j

Joseph Hawkes-Cates

07/26/2022, 8:12 PM
ah yeah, I see what you mean. I’m not sure on a good way to handle that case.
c

Chuck Stein

07/26/2022, 8:14 PM
It seems like I need some way to memoize the item list in the composable so that it keeps items that have been deleted in the view state, until their delete animation completes. And likewise animates new items in the view state list instead of just popping them into existence
a

Alex Vanyo

07/26/2022, 8:59 PM
The approach for
LazyColumn
that is in AnimatedVisibilityLazyColumnDemo would also apply to a normal
Column
. And you’re on the right track, it requires some bookkeeping to keep old items around until their delete animation completes, and using
MutableTransitionState
to avoid the “pop in” effect.
c

Chuck Stein

07/26/2022, 9:12 PM
Thanks! Looking into this now, I'm sure I'll have some follow up questions as I try to implement it
@Alex Vanyo is there any way to do this without tightly coupling your model objects to their UI animation state? That approach just won't work with my app architecture (and probably many others) in which we keep the domain models and view logic very separate
I'm trying to keep a separate
MutableStateList
in the view, containing the model objects + their transition state, and updating that animation-specific list in a
LaunchedEffect
every time the domain model list changes. But I'm having some issues
a

Alex Vanyo

07/27/2022, 8:01 PM
Yep, that sounds like the approach you’d want to take. You could have a
List<Pair<MyItemModel, MutableTransitionState>>
and then you wouldn’t need to change
MyItemModel
at all. There would be a bit of work to create that list, and keep it up to date as the real list updates.
c

Chuck Stein

07/27/2022, 8:17 PM
Okay, I'll keep trying to debug my issues then. Thanks for confirming I'm not trying to achieve something hopeless 👍
@Alex Vanyo Are there any plans to simplify this for the developer in the future, by just using something like an
.animate
modifier, similar to how easy it is with SwiftUI and Flutter? I got a working implementation going without changing my models but it still feels very cumbersome to require all this extra boilerplate compared to similar UI frameworks, and I'm sure a built-in compose version could better optimize it (I'm noticing some lag when typing into the TextFields contained within my list items, causing some text input to get lost)
d

dambakk

08/11/2022, 10:03 AM
I have the exact same use case, a list of x items backed by some state, I want to animate items added/removed, and I cannot use LazyColumn. Do any of you know if there exists a ticket for the feature @Chuck Stein proposes? Would it be possible for me to have a look at your implementation, Chuck? Is it worth implementing it from scratch?
c

Chuck Stein

08/11/2022, 3:37 PM
@dambakk here is my implementation:
And usage looks like this:
Copy code
animatableListItems(items, id = { it.id }).forEach { animatableItem ->
    AnimatedVisibility(visibleState = animatableItem.transitionState) {
        MyListItemComposable(animatableItem.item)
    }
}
where
items
is your list of domain models representing each list item
d

dambakk

08/12/2022, 11:24 AM
Thanks, Chuck! That is some well written code, easy to read, works perfectly! Well done! 👏
c

Chuck Stein

08/18/2022, 2:09 AM
Thank you, I'm glad it helped you out!
276 Views