Search code examples
qmlqt-quickqtquick2

Parallel add and displaced transitions in ListView


In ListView when I add new item with long add transition inserting new items before that item cause displace of that item and stop its add transition processing. How can I workaround this?

import QtQuick 2.0
import QtQuick.Controls 1.0

Item
{
    width: 500
    height: 500

    property ListModel model: ListModel {}

    Button
    {
        id: button
        text: "insert: " + model.count

        onClicked:
        {
            model.insert(Math.round(Math.random() * model.count), {"name": model.count});
        }
    }

    ListView
    {
        model: parent.model
        anchors.top: button.bottom
        anchors.left: parent.left
        anchors.right: parent.right
        anchors.bottom: parent.bottom

        delegate: Text {
            text: name
        }

        add: Transition {
            NumberAnimation { properties: "opacity"; from: 0.0; to: 1.0; duration: 1000 }
        }
    }
}

Solution

  • This problem is clearly discussed in this nice tutorial which is really a good read about transitions and their handling. I highly recommend reading it.

    Citing it directly from the Handling interrupted animations section:

    Each newly added item undergoes an add transition, but before the transition can finish, another item is added, displacing the previously added item. Because of this, the add transition on the previously added item is interrupted and a displaced transition is started on the item instead. Due to the interruption, the opacity and scale animations have not completed, thus producing items with opacity and scale that are below 1.0.

    Hence, what you need is a transition for the displacement. Adding the following code to the ListView should solve your issue:

    displaced: Transition {
        NumberAnimation { properties: "opacity"; to: 1.0; duration: 1000}
    }
    

    The duration can be omitted. It can help to tweak the animation so that speed-ups are avoided (or at least limited). Possibly we can also write:

    displaced: Transition {
            NumberAnimation { properties: "opacity"; to: 1.0; duration: 1000 * (1 - from)}
    }