Animating dynamic ListViews
I am trying to implement a Quick-based menu system which is supposed to be able to add and remove elements dynamically. Insertion and deletion of elements trigger animations. For instance, opacity and height decrease and let elements fade out smoothly.
QAbstractItemModel is visualized by a ListView: "based on the method posted by Denis":http://developer.qt.nokia.com/forums/viewthread/1094
Removing an item from QAbstractItemModel usually destroys the appropriate QML element immediately. Using the ListView.onRemove signal in combination with the ListView.delayRemove property, an animation can be performed before the element actually disappears. However, as soon as this property is utilized, the models represented by ListView and QAbstractItemModel (can) start to differ. As far as QAbstractItemModel is concerned, the element does not exist anymore right away.
QAbstractItemModel on the left, ListView on the right
remove second element:
C B (fading out)
and now insert new element D at position two:
C B (still fading out!)
...wait for animation to finish
C and D are the wrong way around! Basically it is just bad timing.
I devised a small workaround:
- call item->die() and thereby set "die" parameter (role)
- QML element is informed of this change and triggers animation (fade-out)
- the final step of this animation is a ScriptAction which calls method of QAbstractItemModel (e.g. buttonDied())
- buttonDied method removes element from the model (QAbstractItemModel and ListView at the same time)
There is no separate ListView.onRemove handling anymore, changes are performed synchronously.
Component instances are only created for visible elements (which is usually a good thing). Unfortunately, only these elements can be animated. If, for example, all elements are to be removed, the visible elements start to fade out. As soon as they are gone, new elements become visible. All of a sudden, these new elements realize that they are supposed to die and trigger off the animation.
- Is it possible to find out if an item of a model is visible (has an instance)? Maybe ListView::indexAt will do the trick? This way, the animation could be skipped entirely if item is invisible.
- Is there an easier way to keep QAbstractItemModel and ListView synchronized?
This sounds like a bug -- could you add a report to the "bug tracker":http://bugreports.qt.nokia.com?
Fix Version: 4.7.2
Thank you very much!