6

Is there any way to apply animation when we change source of Loader component in QML? For example suppose I have the following Loader:

Loader {
     anchors.fill: parent
     id: loader
}

I want an animation from left to right when I set loader.source = "content.qml"

Thanks for any help.

BaCaRoZzo
  • 7,502
  • 6
  • 51
  • 82
a.toraby
  • 3,232
  • 5
  • 41
  • 73

2 Answers2

5

This is one way to do it:

import QtQuick 2.4
import QtQuick.Window 2.0

Window {
    id: window
    width: 400
    height: 400
    visible: true

    Loader {
        id: loader
        onSourceChanged: animation.running = true

        NumberAnimation {
            id: animation
            target: loader.item
            property: "x"
            from: 0
            to: window.width - loader.item.width
            duration: 1000
            easing.type: Easing.InExpo
        }
    }

    // Replace this with some other action that changes the source.
    Component.onCompleted: loader.source = "MyRectangle.qml"
}

MyRectangle.qml:

import QtQuick 2.0

Rectangle {
    id: rect
    color: "red"
    width: 150
    height: 150
}
Mitch
  • 23,716
  • 9
  • 83
  • 122
  • Thanks. This works, although it was not as nice as I thought it would be. It is not a neat approach to add animation to the loader component. It sometimes run faster and some other times slower and with annoying delay! Thanks anyway. – a.toraby Jul 05 '15 at 07:20
  • 1
    You could try changing `onSourceChanged` to `onStatusChanged` and only start the animation if the `status` is `Loader.Ready`? Without having code to reproduce the slowness, it's hard to offer more advice. You could paste a simplified (but still "heavy") version of the item loaded by the `Loader` so I can try it out. – Mitch Jul 05 '15 at 10:10
4

Is it mandatory to use a Loader?

If it's not, you can use a StackView (of course, having a depth of 1 if you don't want to offer a more complex navigation) and load your components by pushing them on the stack with the replace option set to true.

That said, you can obtain the result you are asking for as follows:

StackView {
    delegate: StackViewDelegate {
        function transitionFinished(properties) {
            properties.exitItem.x = 0
        }

        pushTransition: StackViewTransition {
            PropertyAnimation {
                target: enterItem
                property: "x"
                from: enterItem.width
                to: 0
            }

            PropertyAnimation {
                target: exitItem
                property: "x"
                from: 0
                to: -exitItem.width
            }
        }
    }
}

I apologize if it doesn't work as is (even though it should), but I'm on a mobile phone and I cannot test it right now.

skypjack
  • 49,335
  • 19
  • 95
  • 187
  • I can not use this alternative. I used the Loader component to create a custom Tab View. It's not possible to use Stack View in my case because I need to change only the Tab content not all of page. after all it was useful for someone who prefers stack view. Thanks for your answer. – a.toraby Jul 05 '15 at 06:41
  • @a.toraby Even thought I'm late, simply don't make StackView the root element! – Akash Agarwal Jun 12 '16 at 00:37
  • @skypjack StackView is not Asynchronus – Mahdi Khalili Nov 05 '19 at 07:10