Showing posts with label view switching. Show all posts
Showing posts with label view switching. Show all posts

Sunday, June 7, 2015

Performing Segue and Passing data in iOS

I was trying to learn how to perform view switching using Segue for UI created by StoryBoard. Using Segue is quite easy and convenient. You can create Segue from Interface Builder, which associate action to view. Like if you click some button then you can associate this click action with view switch and you can select which view to switch to. This all is quite simple and can be done using simple drag and drop.

In case you want to perform view switch manually without any user interaction, you can call "performSegueWithIdentifier", like below. Here once my game is finished, I am calling "GameOverSegue", which will switch view to GameOver view.
self.performSegueWithIdentifier("GameOverSegue", sender: self)
If you want to pass some data while performing Segue, your calling ViewController needs to override "prepareForSegue" function. In this function you can set data to called view. Like below, I want to pass score to my GameOver view.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if( segue.identifier == "GameOverSegue") {
        let gameOverVC: GameOverViewController = 
            segue.destinationViewController as! GameOverViewController;
        gameOverVC.setScore(self.score)
    }
}
Thanks, hope this will be helpful.

Sunday, April 13, 2014

Creating Custom Swipe handler in QML

I was often request for sample that shows how custom swipe handler can be created in QML. In this post I will show how same can be achieved.

Please note that code is just prototype level code and is not tested well with actual use. It has also lots of hard coded value that assume certain size of application.

But, you should be able to change those according to your use and can try sample with your app.

This sample implement three QML views and you can swipe on that to change view from one to next. This code also implement some parallax effect on view and view transition animation. In addition to swipe you can also change view using keyboard Left/Right arrow key. Following is demo for the sample app.



So let's start with code.

Following code is from SwipeHandler.qml, it extends MouseArea and try to detect swipe based on mouse's x position change. Swipe can be generated by two way, by flicking on view or dragging it.
Flick is detected, if there is large change in mouse x position in less time. In case of drag, if mouse travel certain distance then code consider it as a swipe.

import QtQuick 2.0

MouseArea{
    id: root

    property int oldX: mouseX;
    property int swipeOffset: 100;
    property int originX:mouseX;

    property var gestureStartTime;
    property bool gestureStarted: false;

    signal swipeEnded(var diff);
    signal swipeContinues(var diff);

    anchors.fill: parent

    onReleased: {
        if( gestureStarted ) {
            //swipe canceled
            root.swipeEnded(0);
            resetGesture();
        }
        //else swipe is already ended
    }

    onPressed: {
        gestureStarted =  true;
        gestureStartTime = new Date();
    }

    onMouseXChanged: {
        if( mouseX < parent.x
        || mouseX > parent.width || gestureStarted == false )
            return;

        if( originX == 0 ) {
            originX = mouseX; oldX = mouseX;
            return;
        }

        var diff = (oldX - mouseX);
        if(handleFlick(diff)){
            return;
        }

        if( haldleDrag(mouseX, diff)){
            return;
        }

        oldX = mouseX;
        root.swipeContinues(diff);
    }

    function resetGesture() {
        originX = 0; oldX = 0;
        gestureStarted =  false;
    }

    function haldleDrag(xPos,xPosDiff){
        if(xPosDiff < 0) {
            if( Math.abs(originX-xPos)  > swipeOffset ){
                root.swipeEnded(xPosDiff);
                resetGesture();
                return true;
            }
        } else {
            if( Math.abs(originX-xPos) >  swipeOffset ){
                root.swipeEnded(xPosDiff);
                resetGesture();
                return true;
            }
        }
        return false;
    }

    function handleFlick(xPosDiff){
        var now = new Date();
        var timeDiff = now - gestureStartTime;

        //high velocity and large diff between start end point
        if(timeDiff < 40 && Math.abs(xPosDiff) > 10 ){
            if(xPosDiff < 0) {
                root.swipeEnded(xPosDiff);
                resetGesture();
                return true;
            } else {
                root.swipeEnded(xPosDiff);
                resetGesture();
                return true;
            }
        }
        return false;
    }
}
So, this was SwipeHandler which can detect if swipe is generated or not. To demonstrate its use, I created a small View Management component, that create's three views. On swipe, view changes form one to another base on direction of swipe movement. Here is code for the same.
import QtQuick 2.0

Rectangle {
    id: root
    width: 200
    height: 300

    property var delegate: comp;

    property var centralView;
    property var nextView;
    property var prevView;

    focus: true

    Component.onCompleted: {
        var colors = ["red","blue","green"];
        var objs = [];
        for(var i =0; i < 3; ++i){
            var obj = comp.createObject(root);
            obj.text = i+1;
            obj.color = colors[i];
            objs.push(obj);
        }

        centralView = objs[0]
        nextView = objs[1]
        prevView = objs[2]

        setViewPos();
    }

    function setViewPos(oldX){
        centralView.animate(50,0);
        nextView.animate(50,root.width);
        prevView.animate(50,-root.width);

        centralView.z = 1;
        nextView.z = 0;
        prevView.z = 0;
    }

    Keys.onRightPressed: {
        var tempView = centralView;
        centralView = prevView;
        prevView = nextView;
        nextView = tempView;

        centralView.animate(150,0);
        nextView.animate(150,root.width);
        prevView.x = -width
    }

    Keys.onLeftPressed: {
        var tempView = centralView;
        centralView = nextView;
        nextView = prevView;
        prevView = tempView;

        centralView.animate(150,0);
        prevView.animate(150,-root.width);
        nextView.x = width
    }

    SwipeArea{
        onSwipeEnded: {
            if(diff === 0) {
                root.setViewPos();
                return;
            }

            var tempView = centralView;
            if(diff < 0) {
                centralView = prevView;
                prevView = nextView;
                nextView = tempView;
            } else {
                centralView = nextView;
                nextView = prevView;
                prevView = tempView;
            }
            root.setViewPos();
        }

        onSwipeContinues: {
            centralView.x = centralView.x - diff;
            if(diff < 0) {
                prevView.x = prevView.x  + Math.abs(diff*1.6);
                prevView.z = 1
                centralView.z = 0;
            } else {
                nextView.x = nextView.x - Math.abs(diff*1.6) ;
                nextView.z = 1
                centralView.z = 0;
            }
        }
    }

    Component{
        id: comp
        Rectangle{
            id: rect
            property alias text: label.text

            width: parent.width; height: parent.height
            Text{
                id: label; anchors.centerIn: parent
            }

            function animate(duration, to){
                anim.to = to; anim.duration = duration
                anim.running = true
            }

            PropertyAnimation{
                id: anim; target:rect; property: "x";duration: 50
            }
        }
    }
}

Saturday, March 5, 2011

Flipping (Rotating) view animation in QML

While I was creating view for my QML application, I thought to add some cool animation effect on view change. So I decided to add view flipping effect on view change event.

I am here sharing simple version of my view flipping code. First in my main view I created simple toolbar with two button, on clicking button it activate or flip according view.

I am skipping toolbar code here, go to end of post to find code for creating toolbar. So to achieve view flipping effect we can use Flipable QML element. We can add front and back to this element and can add animation on Rotation. Folloging code shows how it can be done.
Flipable {
        id: myFlip
        x:0
        y:50
        width: 800
        height: 430

        function showFront() {
            rot.angle=0;
        }

        function showBack() {
            rot.angle=180;
        }

        transform: Rotation {
            id: rot
            origin.x: 400;
            origin.y:100;
            axis.x:0; axis.y:1; axis.z:0
            angle:0

            Behavior on angle { PropertyAnimation{} }
        }

        front: Item {
            Rectangle {
                width: 800
                height: 430
                color:"green"
            }

            Text {
                x: 0
                y:200
                text: "My super cool green view"
            }
        }

        back: Item {

            Rectangle {
                width: 800
                height: 430
                color:"red"
            }

            Text {
                x: 0
                y:200
                text: "My super cool red view"
            }
        }
    }

In above code, I have added two Item element which act as my view and attached it to front side and back side. Then I have added Rotation transformation and added ProperyAnimation when angle changes. Also added two function which shows front or back side by invoking it.

Above code works fine to flip view, but if you have some content in back view then you will see content mirrored. See below snap.


To view proper content we need to remove rotation on content. To do this we can add another Rotation transformation on back view to zero effect of earlier rotation. So our back view code will look like below.
back: Item {

            transform:Rotation {
                origin.x: 400;
                origin.y:100;
                axis.x:0; axis.y:1; axis.z:0
                angle:180
            }

            Rectangle {
                 width: 800
                 height: 430
                 color:"red"
            }

            Text {
                x: 0
                y:200
                text: "My super cool red view"
            }
        }
Now view will look fine, like shown in below pic.


So this was all required to achieve view flipping effect, Following is demo of my sample app.



If you are interested in my simple toolbar then following is code for my toolbar.
    Rectangle {
        id: toolbar
        width:200
        height: 50
        color:"black"

        Image {
            x:10
            y:5
            id: btn1
            source: "btn1.png"

            MouseArea{
                anchors.fill : parent
                onClicked: {
                    console.log("Btn 1 clicked");
                    myFlip.showFront();
                }
            }
        }

        Image {
            x: 60
            y:5
            id: btn2
            source: "btn2.png"
            MouseArea{
                anchors.fill : parent
                onClicked: {
                    console.log("Btn 2 clicked");
                    myFlip.showBack();
                }
            }
        }
    }

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.

Friday, May 14, 2010

View switching on iPhone SDK


While creating sample game for iPhone I required to create menu page for game. Here I am putting down code that I used to create menu for my sample game.

First create a view based application.


Then created menu view as following, with two button that will load new view.

Then add new view controller, I named new view as first view and add button on first view that will switch view to menu screen.


Now connect buttons to message that get activated when button is pressed and when button connection is ready then we can write code that will enable view switching. 

In menu view controller, I used following code to load first view. 

- (IBAction) siwthToView1:(id) sender {        

    FirstView *firstView = 
[[FirstView alloc] initWithNibName:@"FirstView" bundle:nil];

    [self.view addSubview: firstView.view];

}

addSubView message will add new view on view stack and display new view on screen.

Now, in first view I used removeFromSuperview message of UIView to go back to menu view.

removeFromSuperview will remove current view from view stack and displays the superview.


- (IBAction) back:(id) sender {

    [self.view removeFromSuperview];
}

So this was all, by using this simple code I implemented my game's menu page.