I have two views I would like to make a swipe style transition accross and I have done that when there is a segue to act on but the I don't have one here so am not sure how to apply my animation class. All I have in my class is:
let stb = UIStoryboard(name: "Walkthrough", bundle: nil)
let walkthrough = stb.instantiateViewControllerWithIdentifier("walk") as! BWWalkthroughViewController
self.presentViewController(walkthrough, animated: true, completion: nil)
I want to apply apply the following custom segue:
class CustomSegue: UIStoryboardSegue {
override func perform() {
// Assign the source and destination views to local variables.
var firstVCView = self.sourceViewController.view as UIView!
var secondVCView = self.destinationViewController.view as UIView!
// Get the screen width and height.
let screenWidth = UIScreen.mainScreen().bounds.size.width
let screenHeight = UIScreen.mainScreen().bounds.size.height
// Specify the initial position of the destination view.
secondVCView.frame = CGRectMake(0.0, screenHeight, screenWidth, screenHeight)
// Access the app's key window and insert the destination view above the current (source) one.
let window = UIApplication.sharedApplication().keyWindow
window?.insertSubview(secondVCView, aboveSubview: firstVCView)
// Animate the transition.
UIView.animateWithDuration(0.2, animations: { () -> Void in
firstVCView.frame = CGRectOffset(firstVCView.frame, -screenWidth, 0.0)
secondVCView.frame = CGRectOffset(secondVCView.frame, -screenWidth, 0.0)
}) { (Finished) -> Void in
self.sourceViewController.presentViewController(self.destinationViewController as! UIViewController,
animated: false,
completion:nil)
}
}
}
I cannot get it to work any pointers please?
While the first answer should be "use Storyboard Segues", you can solve custom transitions this way:
CustomSegue
to adopt both UIStoryboardSegue
and UIViewControllerAnimatedTransitioning
protocols.CustomSegue
so that the animation can be used by both protocols.delegate
to the navigation controller, which can be itself, to supply the custom transitions to push
& pop
animationControllerForOperation
create and return an instance of CustomSegue
, with an identifier of your choice.Overview
// Adopt both protocols
class CustomSegue: UIStoryboardSegue, UIViewControllerAnimatedTransitioning {
func animate(firstVCView:UIView,
secondVCView:UIView,
containerView:UIView,
transitionContext: UIViewControllerContextTransitioning?) {
// factored transition code goes here
}) { (Finished) -> Void in
if let context = transitionContext {
// UIViewControllerAnimatedTransitioning
} else {
// UIStoryboardSegue
}
}
}
func transitionDuration(transitionContext: UIViewControllerContextTransitioning) -> NSTimeInterval {
// return timing
}
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
// Perform animate using transitionContext information
// (UIViewControllerAnimatedTransitioning)
}
override func perform() {
// Perform animate using segue (self) variables
// (UIStoryboardSegue)
}
}
Below is the complete code example. It has been tested. Notice that I also fixed a few animation bugs from the original question, and added a fade-in effect to emphasize the animation.
// Animation for both a Segue and a Transition
class CustomSegue: UIStoryboardSegue, UIViewControllerAnimatedTransitioning {
func animate(firstVCView:UIView,
secondVCView:UIView,
containerView:UIView,
transitionContext: UIViewControllerContextTransitioning?) {
// Get the screen width and height.
let offset = secondVCView.bounds.width
// Specify the initial position of the destination view.
secondVCView.frame = CGRectOffset(secondVCView.frame, offset, 0.0)
firstVCView.superview!.addSubview(secondVCView)
secondVCView.alpha = 0;
// Animate the transition.
UIView.animateWithDuration(self.transitionDuration(transitionContext!),
animations: { () -> Void in
firstVCView.frame = CGRectOffset(firstVCView.frame, -offset, 0.0)
secondVCView.frame = CGRectOffset(secondVCView.frame, -offset, 0.0)
secondVCView.alpha = 1; // emphasis
}) { (Finished) -> Void in
if let context = transitionContext {
context.completeTransition(!context.transitionWasCancelled())
} else {
self.sourceViewController.presentViewController(
self.destinationViewController as! UIViewController,
animated: false,
completion:nil)
}
}
}
func transitionDuration(transitionContext: UIViewControllerContextTransitioning) -> NSTimeInterval {
return 4 // four seconds
}
// Perform Transition (UIViewControllerAnimatedTransitioning)
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
self.animate(transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)!.view,
secondVCView: transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)!.view,
containerView: transitionContext.containerView(),
transitionContext: transitionContext)
}
// Perform Segue (UIStoryboardSegue)
override func perform() {
self.animate(self.sourceViewController.view!!,
secondVCView: self.destinationViewController.view!!,
containerView: self.sourceViewController.view!!.superview!,
transitionContext:nil)
}
}
class ViewController: UIViewController, UINavigationControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.delegate = self
}
func navigationController(navigationController: UINavigationController, animationControllerForOperation operation: UINavigationControllerOperation, fromViewController fromVC: UIViewController, toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
switch operation {
case .Push:
return CustomSegue(identifier: "Abc", source: fromVC, destination: toVC)
default:
return nil
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With