Search code examples
iosswiftanimationcore-animationsplash-screen

Launch Image Splash Screen Animation in SWIFT


I want to create a twitter like launch image for my ios app in swift.

I do understand the general problem with animated launch images, and I basically know the steps to create such an animation:

  1. Add a new view, right after the app launched, with the exact same content as the launchimage
  2. Animate that view
  3. Let the view disappear

I found this brilliant source: http://iosdevtips.co/post/88481653818/twitter-ios-app-bird-zoom-animation

But this guy uses a mask and I am not able to change his code to get the "real" twitter like animation without a mask, but just an animated (zoom in) image.

So how do I add a new view to the current view? If I use a subview, how do I identify that view later on the progress when I need to delete the subview in animationDidStop?

Oh and I'd love to do all that in the AppDelegate.

Here is my current approach:

Setting up the view in AppDelegate:

import UIKit
import QuartzCore

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var viewForLayer: UIView!
    var window: UIWindow?

    var emoji: CALayer {
      return viewForLayer.layer
    }

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

      self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
      // step 1: recreate the launch image

      self.emoji.backgroundColor = UIColor(red: 52/255, green: 52/255, blue: 52/255, alpha: 0).CGColor
      self.emoji.contents = UIImage(named: "SplashScreenEmoji")!.CGImage

      self.emoji.bounds = CGRect(x: 0, y: 0, width: 100, height: 100)
      self.emoji.anchorPoint = CGPoint(x: 0.5, y: 0.5)
      self.emoji.position = CGPoint(x: self.window!.frame.size.width/2, y: self.window!.frame.size.height/2)

      // self.window!.addSubview(viewForLayer) or
      viewForLayer.layer.addSublayer(emoji)

      // step 2: add the animation to that view
      animateEmoji()

      self.window!.makeKeyAndVisible()
      UIApplication.sharedApplication().statusBarHidden = true
      return true
    }
}

For the animation:

func animateEmoji() {
    let keyFrameAnimation = CAKeyframeAnimation(keyPath: "bounds")
    keyFrameAnimation.delegate = self
    keyFrameAnimation.duration = 1
    keyFrameAnimation.beginTime = CACurrentMediaTime() + 1 //add delay of 1 second
    let initalBounds = NSValue(CGRect: emoji.bounds)
    let secondBounds = NSValue(CGRect: CGRect(x: 0, y: 0, width: 90, height: 90))
    let finalBounds = NSValue(CGRect: CGRect(x: 0, y: 0, width: 1500, height: 1500))
    keyFrameAnimation.values = [initalBounds, secondBounds, finalBounds]
    keyFrameAnimation.keyTimes = [0, 0.3, 1]
    keyFrameAnimation.timingFunctions = [CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut), CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)]
    self.emoji.addAnimation(keyFrameAnimation, forKey: "bounds")
}

override func animationDidStop(anim: CAAnimation!, finished flag: Bool) {
    // step 3: remove the view
    self.viewForLayer.removeFromSuperview()
}

I always get an fatal error: unexpectedly found nil while unwrapping an Optional value, i guess this is because of the

var emoji: CALayer {
   return viewForLayer.layer
}

I definitely stuck and need the help of the stackoverflow community, please don't judge since I am new here and just learn how to code swift ;)

Thanks, jo


Solution

  • You don't need to use layers, you can achieve your zoom effect simply via UIViews and UIView animation blocks.

    Create a custom view controller with just an image view added to its view, assign that view controller as a window's rootViewController. Use a UIView animation block to increase the scale of the image view (via CGAffineTransform). In the animation's completion block, you can assign your actual initial view controller to the window's rootViewController.