Showing posts with label custom view. Show all posts
Showing posts with label custom view. 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
            }
        }
    }
}

Tuesday, July 5, 2011

How to display QWidget into QML

Recently in one of my project I required to embed QWidget derived class to QML scene. While its straight forward to embed QML scene to QWidget or QGraphicsScene.

It required small effort to embed QWidget derived class to QML scene. Still its not great effort and its also vary straigt forward.

All you need to do is, create new class derived from QDeclarativeItem. Create instance of required widget and add that widget to QGraphicsProxyWidget. Now we need to register this newly created class to QML using qmlRegisterType. Now we can use this class from QML which display our QWidget derived class.

Following is code that demonstrate the same. For demo I have created class which embed QLabel to QML scene.

Following code is my custom QDeclarativeItem derive class which will expose QLabel to QML scene.
#include <QDeclarativeItem>

class QLabel;

class QmlLabel : public QDeclarativeItem
{
    Q_OBJECT    
    Q_PROPERTY(QString text READ text WRITE setText)
public:
    explicit QmlLabel(QDeclarativeItem *parent = 0);
    ~QmlLabel();    

public slots:

    void setText(const QString& text);

    QString text() const;

private:

    QLabel* mLabel;
    QGraphicsProxyWidget* mProxy;

};

#include <QLabel>
#include <QGraphicsProxyWidget>

QmlLabel::QmlLabel(QDeclarativeItem *parent) :
    QDeclarativeItem(parent)
{
    mLabel = new QLabel(QString(""));
    mProxy = new QGraphicsProxyWidget(this);
    mProxy->setWidget(mLabel);
}

QmlLabel::~QmlLabel()
{
    delete mLabel;
}

void QmlLabel::setText(const QString& text)
{
    mLabel->setText(text);
}

QString QmlLabel::text() const
{
    return mLabel->text();
}

Following code demonstrate how to register above class to QML. In qmlRegisterType first argument is component uri, which is used for importing component to QML. second and third argument is version information and fourth argument is element name in QML, By using this name we can created QML element.

#include <QtDeclarative>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    qmlRegisterType<QmlLabel>("qmlLabel", 1, 0, "QmlLabel");
    QDeclarativeView viewer;
    viewer.setSource(QUrl("qml/hybrid/main.qml"));
    viewer.show();
    return app.exec();
}

Finally following is QML code. To be able to use our custom QML element we need to import component to QML using import statement.
import QtQuick 1.0
import qmlLabel 1.0

Rectangle {
    width: 360
    height: 360
    QmlLabel {         
        x:100; y:100
        text: "QML Label"
    }
}

Following is out put from above code.

Saturday, March 19, 2011

Custom UIAlertView in iPhoneSDK

Recently while working on personal project I need to customizing UIAlertView. My requirement was just to add image on UIAlertView everything else should be same.

For that I could have derived UIAlertView and could have provided custom drawing to put image, but instead I used following hack because i thought it was fast.

Here is code if you find it useful.
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Hack!" 
      message:@"Hacking alert view\n\n\n\n\n" 
     delegate:nil 
     cancelButtonTitle:@"OK" 
     otherButtonTitles:nil];
 
    UIImageView *imageView = [[UIImageView alloc] 
        initWithFrame:CGRectMake(110, 80, 66, 66)];
 
    NSString *path = [[NSString alloc] initWithString:[[
[NSBundle mainBundle] resourcePath] 
stringByAppendingPathComponent:@"images.jpg"]];

    UIImage *bkgImg = [[UIImage alloc] initWithContentsOfFile:path];
    [imageView setImage:bkgImg];
    [bkgImg release];
    [path release];
 
    [alert addSubview:imageView];
    [imageView release];
 
    [alert show];
    [alert release];

Here is output.

Tuesday, April 27, 2010

Creating custom view for iPhone

Currently I am trying to create simple game for iPhone. To create game first thing I needed to learn is to create custom view and custom drawing. So here I am putting down my learning in hope that it will help some one who started learning iPhone development.

I started with creating new window based project and named it CustomView.


Then I created new class named CustomView and derived it from UIView.


After creating class derived from UIVIew, we need to make sure that application's window add newly created class as its subview like shown in code below. 

- (void)applicationDidFinishLaunching:(UIApplication *)application {   

    CustomView *view = [[CustomView alloc] initWithFrame:window.frame];
   
    // Override point for customization after application launch
    [window addSubview:view];
    [window makeKeyAndVisible];
}

Then finally implement drawRect with custom drawing code. Here is my code with comment, in following code I am drawing a text, a rectangle , a circle and an Image.

- (void)drawRect:(CGRect)rect {
    // Drawing code
    //acquire graphics context
    CGContextRef ctxt = UIGraphicsGetCurrentContext();
   
    //set brush and set brush color to yellow
    CGContextSetFillColorWithColor(ctxt, [[UIColor yellowColor] CGColor]);
   
    //create string to draw
    NSString *hello = @"Hello World!";
    //create font to be used
    UIFont* font = [UIFont systemFontOfSize:20];
   
    //find horizontal center position for text
    int xLocation = ([self frame].size.width / 2) - ( [hello sizeWithFont:font].width /2 );
    [hello drawAtPoint:CGPointMake( xLocation, 100 ) withFont:[UIFont systemFontOfSize:16.0]];
   
    //draw rect
    CGContextFillRect(ctxt, CGRectMake(50, 50, 50, 50));
    //change brush color to green and draw circle
    CGContextSetFillColorWithColor(ctxt, [[UIColor greenColor] CGColor]);
    CGContextFillEllipseInRect(ctxt, CGRectMake(150, 150, 50, 50));
   
    //draw image
    UIImage *image = [UIImage imageNamed:@"red-ind.png"];
    [image drawAtPoint:CGPointMake( 100,200)];
}

So end result looks like following.