Adding UIKit Elements on top of Sparrow

Sparrow renders all its contents directly into the view object of its SPViewController. Since the view is a normal UIView object, you can add any conventional UIKit view objects on top of Sparrow. The UIKit objects will always be drawn on top of the Sparrow elements, though; you cannot place Sparrow elements on top of UIKit elements.

Mission Objective

In this tutorial, we will add a simple UISwitch object on top of Sparrow. Changing the state of the switch will then affect the color of an object within the Sparrow display tree.

While the sample itself does not look super-useful, it will show everything you need to know to be able to combine UIKit and Sparrow elements in interesting ways.

This is how the scaffold app looks like in its original state:

Adding the Switch

The unmodified version of the Scaffold project plays a sound when you touch the bird. Let's say we want to show the UIKit switch instead. To do this, we add a new method call to the event handler.

- (void)onImageTouched:(SPTouchEvent *)event
{
    NSSet *touches = [event touchesWithTarget:self andPhase:SPTouchPhaseEnded];
    if ([touches anyObject])
    {
        [self showSwitch];
    }
}

The showSwitch method is responsible for adding that switch. For this to happen, add the member variable _switch to the class, and implement the showSwitch method like this:

@implementation Game
{
    SPSprite *_contents;
    UISwitch *_switch; // <- Add the member variable here
}
 
- (void)showSwitch
{
    if (!_switch)
    {
        _switch = [[UISwitch alloc] initWithFrame:CGRectMake(15, 15, 0, 0)];
        [_switch addTarget:self action:@selector(onSwitchValueChanged)
                 forControlEvents:UIControlEventValueChanged];
 
        [Sparrow.currentController.view addSubview:_switch];
    }
}
 
- (void)onSwitchValueChanged
{
    NSLog(@"switch value: %d", _switch.isOn);
}

This is where it gets interesting! Creating the UISwitch is straight-forward; just init the class and add a UIKit-style event handler.

But how do we get access to the basic UIKit view object? In Sparrow 2, you can access that object from anywhere in your code like this:

SPViewController *viewController = Sparrow.currentController;
UIView *view = currentController.view;

The currentController method of the Sparrow class always points to the view controller you created in the Application delegate. And that controller contains a reference to the UIView object it renders into. Thus, you can easily access that view from anywhere in your game with the one-liner we're using in the showSwitch method.

Now let's start up the project and see what happens. After tapping the bird, the switch should appear, and Xcode should log 1s and 0s when its state changes.

Updating the Bird

To make it a little more interesting, we modify the event handler so it changes the color of the bird.

- (void)onSwitchValueChanged
{
    NSLog(@"value: %d", _switch.isOn);
 
    SPImage *bird = (SPImage *)[_contents childAtIndex:2];
    bird.color = _switch.isOn ? SP_RED : SP_WHITE;
}

(It would have been cleaner to save the bird object as a member variable instead of accessing the child at index '2', but I'll leave that as an exercise for you ;-) ).

That should be it! You successfully added an UIKit object on top of Sparrow and are using it to modify a Sparrow display object! Cool, isn't it? Now you can add any other UIKit element just like that.

Universal Apps

There's one more thing you need to take care of. If you are developing a universal application with the doubleOnPad: strategy of Sparrow, the coordinate system of UIKit won't be the same as that of Sparrow. Remember, Sparrow will double the content scale factor in that case (it's called doubleOnPad: for a reason), but UIKit doesn't know about that.

For this reason, you have to multiply the coordinates of your UIKit objects by a certain factor; on the iPad (both retina and non-retina), that factor will be 2.0.

To find out the required multiplication factor at runtime, you can simply divide “Sparrow.contentScaleFactor” by
“Sparrow.currentController.view.contentScaleFactor”.

Also note that some standard interface elements (e.g. switches) have a fixed size and should not be scaled. You have to take that into account when you place those objects on the screen.


Continue to Dynamic Textures

  manual/adding_uikit_elements_on_top_of_sparrow.txt · Last modified: 2014/08/25 08:32 by daniel
 
Powered by DokuWiki