Twitter style opening transition
Create a Launch Screen
Grab the Twitter logo which you can download from Twitter's Brand Resources page, add it to the asset library and using constraints centre it in the LaunchScreen.storyboard
Apple will instantly transition from this to the project start page.
Add Splash ViewController
A view to transition from—which matches the launch screen—is needed. Duplicate the launch screen in the Main.storyboard
and ensure it's set as the storyboard entry point.
Add a backing class and immediately present your main applications starting page in the viewDidAppear
.
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let storyboard = UIStoryboard.init(name: "Main", bundle: nil)
let controller = storyboard.instantiateViewController(withIdentifier: "mainApplication")
self.present(controller, animated: true, completion: nil)
}
Note: Remember to add a Storyboard ID
to be able to instantiate your applications starting page.
Implement custom transition
All of the custom transition code will be added to a single class that implements UIViewControllerAnimatedTransitioning
.
class SplashTransition: NSObject, UIViewControllerTransitioningDelegate {
}
The transition class is wired up via a delegate.
override func viewDidAppear(_ animated: Bool) {
//...
controller.transitioningDelegate = transition
self.present(controller, animated: true, completion: nil)
}
And will need to be a strong reference so that it's not immediately deallocated.
fileprivate var transition: SplashTransition?
override func viewDidLoad() {
super.viewDidLoad()
self.transition = SplashTransition()
}
Replicating the basic animation it is fairly easy, implemented as a CALayer mask on the destination view.
let start = UIBezierPath(ovalIn: frame).cgPath
let layer = CAShapeLayer()
layer.path = start;
layer.add(animation, forKey: "path")
toView.layer.mask = layer
With the animation simply increasing to a size larger than the destination view.
let finish = UIBezierPath.init(ovalIn: frame.insetBy(dx: -radius, dy: -radius)).cgPath
let animation = CAKeyframeAnimation.init(keyPath: "path")
animation.duration = 0.7
animation.timingFunctions = [CAMediaTimingFunction(name:.easeInEaseOut)]
animation.values = [start, finish];
animation.keyTimes = [0, 0.7]
Update the custom transition Mask
Finally—for extra merit—change the CAShapeLayer
to a simple CALayer
, add the image and animate it's bounds