Open doors effect at App launch



This is a copy of a blog entry I originally wrote for ios-blog

There are a number of apps in the App Store that launch with a set of closed doors, these are then opened to present the actual UI underneath it.

I had to create this effect for an app I wrote for a client http://itunes.com/apps/jkmuaythai

I’d assumed when I started that this would be a relatively simple task, just take the initial default image, cut it in half and a simple bit of animation would move them out of the way. What I hadn’t counted on is getting the orientation of the device from launch is not straightforward. The trick is to remember that the first view that is loaded will always assume it’s in Portrait mode, the view is then informed via the willRotate method that in fact the orientation is different and you can then handle this appropriately. The second trick is knowing that the willRotate takes a little bit of time to fire, so it’s now a simple case of delaying the call to the method that handles the animation.

The viewWillAppear method loads the images assuming that the view is in portrait and sets up a timer to call the openDoors method

-(void)viewWillAppear:(BOOL)animated {
    //All apps start in portrait mode, with the home button at the bottom,
    //If the device is being held with the home button in any other location then a
    //willRotate is fired!
    isPortrait = YES;
    doorsClosed = YES;

    //We assume we are in portrait mode until told otherwise
    self.leftDoor.image = [UIImage imageNamed:@"DoorLeftiPadPortrait.png"];
    self.rightDoor.image = [UIImage imageNamed:@"DoorRightiPadPortrait.png"];
    self.backgroundSplash.image = [UIImage imageNamed:@"SlideBackgroundiPadPortrait.png"];

    //Add a delay to the open doors sequence, this allows the OS to determine
    //the correct orientaion and fire the all important willRotate

    [NSTimer scheduledTimerWithTimeInterval: 3.5
                                     target: self
                                   selector: @selector(openDoors)
                                   userInfo: nil
                                    repeats: NO];
}

The willRotate method then ensures that the correct image is loaded

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    return YES;
}

-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    isPortrait = UIDeviceOrientationIsPortrait(toInterfaceOrientation);
    if (!isPortrait) {
        //If the doors haven't already been opened then change them to the landscape ones
        if (doorsClosed) {
            self.leftDoor.image = [UIImage imageNamed:@"DoorLeftiPadLandscape.png"];
            self.rightDoor.image = [UIImage imageNamed:@"DoorRightiPadLandscape.png"];
        }
        self.backgroundSplash.image = [UIImage imageNamed:@"SlideBackgroundiPadLandscape.png"];
    } else {
        self.backgroundSplash.image = [UIImage imageNamed:@"SlideBackgroundiPadPortrait.png"];
    }
}

The openDoors method then just works out how far to move the images and kicks of the animation, I’ve included the old UIView beginAnimation and the Blocks way

-(void)openDoors {
    //Determine how far the doors need to move for them to disappear from view
    float adjust = (CGRectGetWidth(self.view.frame) > CGRectGetHeight(self.view.frame)) ? CGRectGetWidth(self.view.frame) : CGRectGetHeight(self.view.frame);
    //Retrieve the original frame and then adjust the X position accordingly
    CGRect leftFrame = self.leftDoor.frame;
    CGRect rightFrame = self.rightDoor.frame;;

    leftFrame.origin.x = -adjust;
    rightFrame.origin.x += adjust;

//Old School Animation

//Set up the animation, change the frames and commit it
//	[UIView beginAnimations:@"swipe" context:nil];
//	[UIView setAnimationDuration:1.2];
//	[UIView setAnimationDelay:0.0];
//	[UIView setAnimationDelegate:self];
//
//      self.leftDoor.frame = leftFrame;
//	self.rightDoor.frame = rightFrame;
//
//	[UIView commitAnimations];

//Blocks
    [UIView animateWithDuration:1.2
                     animations:^{
                        self.leftDoor.frame = leftFrame;
                        self.rightDoor.frame = rightFrame;
                     }
    ];

    doorsClosed = NO;
}

Note this effect only works if the app is launching for the first time, i.e. not from the background.

I’ve put together a sample project that puts this all into practice

https://github.com/Flexicoder/OpenDoorsDemo

Hope you find this useful, or if you have a better way of creating the same effect please let me know

See what I do

Mobile Apps – Ballpark Costs

When potential clients ask for a ballpark figure on development costs, these are the questions I ask to help clarify whats required and therefore affect the cost. They are in no particular order…

  • What are the target platforms, iPhone, iPad, Android, Windows Mobile?
  • If they want multiple platforms are they aware that native apps are developed using different languages
  • If iPhone do you want a universal version, i.e. the same app runs on iPhone and iPad (thanks @ithain)
  • Whats the target audience?
  • Do you have an idea of how you want the app to flow?
  • Are there existing apps out there that do something similar, if there are what are they and what will make this one different?
  • Are there existing apps that you like the style of or the way they work?
  • Will you apply for your own developers licences so that the app is submitted under your name?
  • Will the app be free, sold for a one off fee, have in-app purchases or have subscriptions?
  • Who will supply the artwork?
  • Does the app need to be location aware?
  • Ideas of timescale for release? (thanks @MrAntix)
  • Are there any hosting requirements? (thanks @MrAntix)
  • Third party services integration requirements? (thanks @MrAntix)
  • Any social media integration?
  • Any security requirements, OAuth, Encryption, etc? (thanks Gary)
  • What is the lowest version of the operating system for a device that needs to be supported
  • Does the app need to support Push Notifications, if yes how will they be delivered in house or third party (UrbanAirship)

And if the app contains dynamic data the following are also important questions…

  • How will the app access the data?
  • Have the web services that supply the information been designed/written?
  • Would you require a content management system to update information contained in the app?
  • If its a Corporate app, what back end data do you need to access and synchronise (thanks @ithain)

Update 2 Extra items thanks to @adrian_bigland
Internationalisation:

  • how many languages need to be supported
  • who will do the translation
  • how will translations be tested – often you need to write code to present all the error dialogs etc. for ease of checking.
  • different UI layouts, or will all the languages fit? German always stresses label lengths, and non FIGS languages might need their own screens, in extreme cases.

Offline support:

  • do you need to store data from web services, so that when you are offline, the experience is seamless?
  • can the user upload information from the app? You often need to store events for analytics while offline, for example.
  • are you going to have problems merging external and local changes? (This way, madness lies).

Custom components?

End of update

Obviously the answers to these questions are likely to lead to more specific questions, but it helps with the thought process involved with what might be required

I would be really interested to know if there are any other questions you ask that I’ve not included?

UPDATE: The first question I am going to start asking is if they have a budget in mind, some projects can be completed in 5 days, some in 5 months, but if they think that they can get the next instagram for £1K, they are wasting my time and their own.

See what I do