Friday, December 17, 2010

Simple view switching animation with Qt Quick (QML)

Code updated after comment received from "mich", now code looks much better.
---------------------

Now that I have some free time and no work to do, I thought to play with QML and created simple demo that implement views and changes view on swipe event.

As of now I don't have latest QML installed, therefor I am not able to use GestureArea QML element to detect swipe gesture and decided to implement my own swipe detection code in QML.

In demo, view is quite simple just showing colored rectangle and string. My intention for demo was to create reusable view element and to change view from one to another.

My view code is as below, I am calling it as screen in code and named QML file as Screen.qml. Mainly screen element maintain states to hide and show view and animate the transition. In real world it might required lots of other property and function but my implementation have only few.
import Qt 4.7

Item {
    id: screen
    property string color: "red"    
    property string title: "title"
    opacity: 1    

    function hide() {
        screen.state = 'hide';
        screen.x = 0;
    }

    function show(xVal) {        
        screen.x = xVal;        
        screen.state  = 'show';
    }

    Rectangle {
        id: rect
        width: 480
        height: 640
        color:  screen.color
    }

    Text {
        id: title
        text: screen.title;
    }

    states: [
             State {
                 name: "show"
                 PropertyChanges {
                     target: screen
                     x: 0
                     opacity:1
                 }
             },
             State {
                 name: "hide"
                 PropertyChanges {
                     target: screen
                     opacity:0
                 }
             }
         ]

    transitions: [             
             Transition {
                 from:"hide"
                 to:"show"
                 NumberAnimation { properties: "x"; duration:500}                 
                 NumberAnimation { properties: "opacity"; duration: 700 }
             },
             Transition {
                 //from: "show"
                 to: "hide"
                 NumberAnimation { properties: "opacity"; duration: 700 }
             }
         ]
}
In my main.qml entry qml code, I have swipe detection code and view switching code as below.
import Qt 4.7

Rectangle {
    id: container
    width: 480
    height: 640    
    property int currentScreen: 0
    property int previousScreen: 0

    //creating array of screens
    property list<item> screens: [
    Screen {
            parent: container
            id: firstScreen
            title:"First Screen"
            color: "blue"
        },
        Screen {
            parent: container
            id: secondScreen
            title:"Second Screen"
            color: "red"
        },
        Screen {
            parent: container
            id:thirdScreen
            title:"Third Screen"
            color:"green"
        },
        Screen {
            parent: container
            //anchors.fill: parent
            id:fourthScreen
            title:"Fourth Screen"
            color:"orange"
        }
        ]

    Component.onCompleted: {
           console.log("Startup script");
           container.currentScreen = 0;
           container.previousScreen = 0;
           for(var i=0; i < 4; ++i) {
           screens[i].hide();
       }
       screens[0].show(0);
    }

    // function to show particular view 
    function showScreen(screenNo,direction) {
      screens[previousScreen].hide();
       var xVal = direction == -1 ? 400 : -400;
       screens[screenNo].show(xVal);
    }
    
    // function to switch view on swipe
    function onLeftSwipe() {
        previousScreen = currentScreen;
        currentScreen = currentScreen +1;
        if(currentScreen > 3 ) {
            currentScreen = 0;
        }
        showScreen (currentScreen,-1)  ;
    }

    function onRightSwipe() {
        previousScreen = currentScreen;
        currentScreen = currentScreen -1;
        if(currentScreen < 0 ) {
            currentScreen = 3;
        }
        showScreen (currentScreen,1)  ;
    }

    // swipe detection code
    MouseArea {
        id: mouseArea
        anchors.fill: parent;

        property int oldX: 0
        property int oldY: 0

      onPressed: {
        oldX = mouseX;
        oldY = mouseY;
      }

      onReleased: {
          var xDiff = oldX - mouseX;
          var yDiff = oldY - mouseY;
          if( Math.abs(xDiff) > Math.abs(yDiff) ) {
              if( oldX > mouseX) {
                    onLeftSwipe();
              } else {
                    onRightSwipe();
              }
          } else {
              if( oldY > mouseY) {/*up*/ }
              else {/*down*/ }
          }
       }

    }
}

Overall I felt there is lot more to do to create truly reusable view code,but this is all for now.

9 comments:

  1. My realization is some different http://nopaste.info/57f185139e.html

    ReplyDelete
  2. @mich, Thanks for sharing, link is good resource, I was searching for something like this.

    ReplyDelete
  3. Hello Kumal,

    Executive summary: thanks for sharing.

    Nit: I suspect the software you used to format the code munged it a little bit. In particular, the syntax of property list needs the type (ie, Screen) in angle brackets. Also, the comments in the onReleased method will comment out the ending curly bracket.

    -jk

    ReplyDelete
  4. Thanks jk for comment,

    I will try to paste properly formated code.

    -kunal

    ReplyDelete
  5. when you will paste the formated code?

    ReplyDelete
  6. Hi, Thanks John for pointing out errors,

    I resolved those formatting problem in post, please let me know if there are still some problems.
    ~Kunal

    ReplyDelete
  7. Hello kunal , i m using lib in Qml . this lib is create in Qt/c++.
    i have create hello world progam in Qml( default program in Qt Quick ui). i m use visible property in Qml. i m using parent.visibility = false. then disply
    Gui from lib . and skip the lib GUI enterd the Hello world app . i m using parent.visibiliy = true. but i m getting blank secreen. pls give me answer my Question.

    ReplyDelete
  8. your property array should have 'item' capitalized:

    property list screens:
    should be:
    property list screens:

    ReplyDelete
    Replies
    1. sorry, formatting botched. Just capitalize the first letter of the word 'item' to 'Item'

      Delete