Tuesday, March 22, 2011

Getting Animation start ,stop event in QML

While working on my hobby QML Project, I required to detect when particular animation got completed

Well its quite simple to achieve this but initially I struggled with it, I was trying to use onCompleted signal to detect animation end, but latter realised that it comes from component and not from animation.

Actual signal we want to use is onRunningChanged and we can check animation's running property to decide if animation is started or ended. Following is my sample QML code to detect Animation start and stop.
Behavior on rotation {
        PropertyAnimation {
            id: rotAni;
            duration: 500 ;
            onRunningChanged: {
                if (!rotAni.running) {
                    console.log("Animation completed");
                } else {
                    console.log("Animation started");
                }
            }
        }
    }
As requested in comment, I am posting similar example for NumberAnimation as well.
Rectangle {
        width: 360
        height: 360

        gradient:first
        Gradient {
            id:first
            GradientStop { position: 0.0; color: "red" }
            GradientStop { position: 0.33; color: "yellow" }
            GradientStop { position: 1.0; color: "green" }
        }
        Gradient {
            id:second
            GradientStop { position: 0.0; color: "red" }
        }

        MouseArea{
            anchors.fill:parent
            onClicked: {
                parent.gradient=second
                numAni.running = true;
            }
        }

        NumberAnimation{
            target:smallRect
            id:numAni
            properties: "x";
            to: 100;
            duration: 1000

            onRunningChanged:{
                if (!numAni.running) {
                    console.log("numAni Animation completed");
                } else {
                    console.log("numAni Animation started");
                }
            }
        }

        Rectangle{
            id:smallRect
            width:10;
            height:10;
        }
    }

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.

Sunday, March 13, 2011

Snake game for Symbian phones

Recently I ported my snake game to Symbian platform. It was already developed using Qt so I did not required to do much.I just used some graphics and made change to accommodate Symbian device's screen resolution.

Following is game play video on my C7 device. Game is available on Ovi Store, download it from here.



Here are few snaps from game.



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, March 4, 2011

Creating custom ListView delegate in QML

Currently I am trying to port one of my application's view to QML. During porting activity I need to create custom ListView delegate. In any case it looks like in QML ListView dose not provide any default delegate so you need to create one.

So I wanted to put button on my every row of ListView and wanted to emit signal when that button is pressed.

Something like this.(This is final out put of my QML code)


So I began with simple ListView with basic delegate as shown in below code.

import Qt 4.7

Rectangle {
    width: 250
    height: 300

    Component {
        id: listDelegate
        Item {
        width: 250; height: 50
        
            Row {
             Column {
                 width: 200
                 Text { text: 'Name: ' + name }
                 Text { text: 'Cost:' + cost }
                }
            }
        }
    }

    ListModel {
             id: listModel

             ListElement {
                 name: "Apple"; cost: 2.45
             }
             ListElement {
                 name: "Banana"; cost: 1.95
             }
     }

    ListView {
          id: listView
          anchors.fill: parent; anchors.margins: 5
          model: listModel
          delegate: listDelegate
          focus: true
    }
}

Out put will look like below. In above code delegate is created to display one colum with two text element.



Now I need to add image in above item delegate which will act as button and will propogate click event with index of item being clicked.

To add image to item delegate I am adding another column to row element and adding image element in that, also handling various mouse event to simulate button.
Component {
             id: listDelegate

             Item {
                 width: 250; height: 50

                 Row {
                     Column {
                         width: 200
                         Text { text: 'Name: ' + name }
                         Text { text: 'Cost:' + cost }
                     }
                     Column {
                        width: 50
                        Image {
                          id: itemBtn
                          source: "btn1.png"
                          MouseArea {
                              anchors.fill: parent;
                              onEntered: {
                                  itemBtn.source= "btn2.png";
                              }

                              onExited: {
                                    itemBtn.source= "btn1.png";
                              }

                              onCanceled: {
                                    itemBtn.source= "btn1.png";
                              }

                              onClicked:{
                                  console.debug("clicked:"+ index);
                                  listView.currentIndex = index;
                              }
                          }
                       }
                    }
                }
             }
         }  

So it will look like below.

This is all. In case you want to add highlight to list then you can use following code. You need to add this code to Rectangle element of qml file. Please note that in above code, highlight only moves when you click button or you use keyboard arrow key.
Component {
          id: highlightBar
          Rectangle {
              width: 245; height: 40
              radius: 5
              color: "lightsteelblue"
              y: listView.currentItem.y;
              x: listView.currentItem.x-3;
              Behavior on y { PropertyAnimation {} }
          }
      }


And also you will need to change ListView element to set highlight like below.
ListView {
          id: listView
          anchors.fill: parent; anchors.margins: 5
          model: listModel
          delegate: listDelegate
          highlight: highlightBar
          highlightFollowsCurrentItem: false
          focus: true
    }

Thats all, hope this helps.