When using `Modifier.animateItemPlacement` in a li...
# compose
z
When using
Modifier.animateItemPlacement
in a list, Ive noticed that elements with different sizes will sometimes overlap during the animation. This breaks the whole surface thing that material has going. Im wondering if this is a known issue that anyone else has ran into?
🇸🇪 5
s
How would you expect this to function optimally? If items are reordered there must be some time where items are on top of each other no?
z
In the good old XML days, the items would never overlap (exception being when they have to cross paths, e.g. after being reordered). Im expecting something similar to happen here. IIRC, views could never overlap in a LinearLayout, etc, and I think this is the result of that no longer being true in compose? Things are generally within their bounds, but Ive seen plenty of cases where a long text might draw outside of its wrapping box/col/row.
a
do you have “keys” specified for all elements? it could be possible that the line with “Dag 1, etc” is not animated via animateItemPlacement and instead moving just because the size of the first element is changing, but the rest of items are reacting on it via animateItemPlacement
z
@Andrey Kulikov Yep, all elements in the list have stable keys! The animation is much better if I remove animateItemPlacement altogether, but I do need it for other use cases. Im animating the input fields container using animateContentSize, and in conjunction with animateItemPlacement it feels like the two animations happening simultaneously is what produces.. whatever this is 😄
a
yes, there are two animations for sure. however you can see from your video that your lines with “Vecka” and the two blue ones move together, but the line starting with “Dag 1" is not moving with them. this makes me thing that animateItemPlacement is not correctly configured for this line. or it is missing keys, or modifier is not applied. maybe it is applied not to the direct child of LazyColumn for example?
z
Thanks, @Andrey Kulikov! I think I found the culprit - Im using AnimatedContent on the input fields to transition between Text/Input, and on top of that animateContentSize is happening on ther container wrapping them. It seems to me like one animation makes some waves due to its interpolator, which is good; but the two together make waaay bigger waves. Dunno if thats a good analogy, but thats how I think about it 😛
a
yeah, do not overwave 🙂
d
This is a more fundamental problem with layout animation: Layout animations affect siblings' sizes and positions, but siblings have no visibility of what the target for those animations are as they are self-contained. In this case, the
animateItemPlacement
is probably being interrupted every frame because the
animateContentSize
would grow input fields in size, consequently the placement target changes.
LookaheadLayout
will solve this problem by doing a lookahead pass using the post-animation sizes & positions, and thus allowing all layouts in
LookaheadLayout
to observe their post-animation size and position. In the next major release, we'll make changes to
animateContentSize
so that the target size is observable in the lookahead pass. In that case,
animateItemPlacement
can rely on the (more stable) lookahead placement, rather than a per-frame current position, as animation target.