I've read the other posts on segues but none solve my question.
Simply put, my ViewController
s are ordered, like a book. I want backward transitions (example: from page 9 to 8) to always present (slide over) from left to right. I want forward transitions (from page 9 to 10) to present from right to left.
Yes, my nav-controller back button (top left) presents like this if you are paging through page by page. However, if you jump in from an Index then the back function on the nav controller takes you back to the index.
My objective is that if a user jumps to page 9 (for example) from an index, then swipes right, it'll flick the page off to the right and show page 8. Once on page 8, if they flick left the page will get flicked off to the left and they'll be on page 9 again.
All my ViewController
s are by, default, presenting by sliding in from right to left.
Example: Think of it like a book, if I use the Index to hop to chapter 4, then swipe right and pop a view from the stack, I'll be back at the Index. But if you're on Chapter 4, page 394 and you swipe right, you don't want to go back to the index! You want to go to the last page of chapter 3, page 393! So the nav stack is no help to me.
End Example
Details: 1. I'm using the new Xcode "Show" on button-tap to switch between ViewControllers.
I'm using a navigation controller, for the top-left "Back" button functionality. This uses the nav stack and works fine.
However I have my own custom nav-bar at the bottom (Back Button, Home Button, Index Button, Forward Button) and gestures. These are what I want to have book-like functionality with.
Coding in swift.
Working with Xcode 6.3
I've read that there's animation code. I've read there's in depth programatic transitions that can be used. It just seems crazy that there's no simple way to just select the segues I want to present from the left and easily reverse the animation.
Thanks!
Attempt log:
I tried DCDC's code:
UIView.transitionWithView(self.window!, duration: 0.5, options:.TransitionFlipFromLeft, animations: { () -> Void in
self.window!.rootViewController = mainVC
}, completion:nil)
This error is returned when I insert DCDC's code into an IBAction
for my back-swipe
This is how I achieve the effect without requiring a nav-controller. Try this instead:
Swift 4:
import UIKit class SegueFromLeft: UIStoryboardSegue { override func perform() { let src = self.source let dst = self.destination src.view.superview?.insertSubview(dst.view, aboveSubview: src.view) dst.view.transform = CGAffineTransform(translationX: -src.view.frame.size.width, y: 0) UIView.animate(withDuration: 0.25, delay: 0.0, options: .curveEaseInOut, animations: { dst.view.transform = CGAffineTransform(translationX: 0, y: 0) }, completion: { finished in src.present(dst, animated: false, completion: nil) } ) } }
Swift 3:
import UIKit class SegueFromLeft: UIStoryboardSegue { override func perform() { let src = self.sourceViewController let dst = self.destinationViewController src.view.superview?.insertSubview(dst.view, aboveSubview: src.view) dst.view.transform = CGAffineTransformMakeTranslation(-src.view.frame.size.width, 0) UIView.animateWithDuration(0.25, delay: 0.0, options: UIViewAnimationOptions.CurveEaseInOut, animations: { dst.view.transform = CGAffineTransformMakeTranslation(0, 0) }, completion: { finished in src.presentViewController(dst, animated: false, completion: nil) } ) } }
Then in the storyboard, click on the segue you'd like to change. In the attributes inspector change the type to 'Custom' and change the class to 'SegueFromLeft'
Here is a custom-segue class you can use to perform a left-to-right segue in Swift. It requires QuartzCore framework and minimal animation.
Swift 2.2
import UIKit import QuartzCore class SegueFromLeft: UIStoryboardSegue { override func perform() { let src: UIViewController = self.sourceViewController let dst: UIViewController = self.destinationViewController let transition: CATransition = CATransition() let timeFunc : CAMediaTimingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) transition.duration = 0.25 transition.timingFunction = timeFunc transition.type = kCATransitionPush transition.subtype = kCATransitionFromLeft src.navigationController!.view.layer.addAnimation(transition, forKey: kCATransition) src.navigationController!.pushViewController(dst, animated: false) } }
Swift 3.0
import UIKit import QuartzCore class SegueFromLeft: UIStoryboardSegue { override func perform() { let src: UIViewController = self.source let dst: UIViewController = self.destination let transition: CATransition = CATransition() let timeFunc : CAMediaTimingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) transition.duration = 0.25 transition.timingFunction = timeFunc transition.type = kCATransitionPush transition.subtype = kCATransitionFromLeft src.navigationController!.view.layer.add(transition, forKey: kCATransition) src.navigationController!.pushViewController(dst, animated: false) } }
The "Back" button will still appear in the navigation bar on the transitioned view controller, but you can easily disable/configure the navigation controller for that view controller.
Updated accepted answer in Swift 3:
import UIKit
class SegueFromLeft: UIStoryboardSegue
{
override func perform()
{
let src = self.source
let dst = self.destination
src.view.superview?.insertSubview(dst.view, aboveSubview: src.view)
dst.view.transform = CGAffineTransform(translationX: -src.view.frame.size.width, y: 0)
UIView.animate(withDuration: 0.25,
delay: 0.0,
options: UIViewAnimationOptions.curveEaseInOut,
animations: {
dst.view.transform = CGAffineTransform(translationX: 0, y: 0)
},
completion: { finished in
src.present(dst, animated: false, completion: 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