Well, trick question, I know it's possible as there's a few apps doing it, notably Reeder does it very well.
In Reeder, it seems that the view controller that gets popped does not get removed from memory, or whatever the typical behaviour is, because after popping and returning to the previous view controller, you can slide right-to-left to peek a little, and if you were scrolling the previous view controller before leaving, you can still see the scrolling occur. This ability to quickly jump back to the previous view controllers you were looking at, without having to preload them from scratch is exactly what I'm looking for.
Basically, in iOS 7 by default when you slide to the right from the left edge of a view controller it pops it off the navigation stack. I'd love for the ability to slide to the left from the right edge to add it back. Think of this as in a web browser you're able to click the "Forward" button after pressing back. (Or in iOS 7's Safari how you can do exactly this.)
Is this functionality part of iOS 7 by default and I just can't find it? Or is there any information on how to go about accomplishing it?
The options depend upon the iOS versions you're trying to support.
In iOS 7+, you can use custom view controller transitions and implement interactive view controller transitions. For a conceptual description, see WWDC 2013 video Custom Transitions Using View Controllers. The basic process is:
Create an animation controller that defines what the animation is to be. The animation controller is an object that conforms to UIViewControllerAnimatedTransitioning
. (Note, it might seem odd to have to define a custom animation controller for something as standard as a push animation, but below you'll see we want a gesture recognizer to interface with an interaction controller, but you cannot define a custom interaction controller if you don't also define a custom animation controller.)
Instantiate an interaction controller. You can create your own interaction controller class that conforms to UIViewControllerInteractiveTransitioning
, but it's easiest to simply instantiate aUIPercentDrivenInteractiveTransition
object.
Now that you have the interaction controller, you can link a gesture recognizer (e.g. a UIScreenEdgePanGestureRecognizer
), to it. The gesture recognizer will call calling the interaction controller's updateInteractiveTransition
to specify the progress of the animation as it corresponds to the continuous gesture.
Clearly, if you're going to recognize a swipe from the right edge as a "push" to a particular scene, then you'll have keep track of what that "next" scene is going to be. Sometimes you'll have a predefined series of view controllers. Sometimes you'll just keep an stack of view controllers that you previously popped from so that you can swipe from the right to push them back on. It just depends upon the desired UX.
The iOS 7 customer transitions provides incredible control in customizing both the animations and gestures linked to the interactive transition. But it takes a little work to do this right.
If you're just looking for an easier way to simply do slide transitions between a series of view controllers, you can use a UIPageViewController
. In iOS 6 and later, you can employ a transitionStyle
of UIPageViewControllerTransitionStyleScroll
. (Unfortunately, in iOS 5, you only had the page curl transition.)
In iOS 5+ and later, you can also do this yourself using custom container controller, manually adding the child view controller views, change the frames during the gesture. Clearly, you have to do all of the custom container calls, too (e.g. addChildViewController
, removeChildViewController
, willMoveToParentViewController
, didMoveToParentViewController
, etc.). See WWDC 2011 video Implementing UIViewController Containment or Creating Custom Container View Controllers section of the View Controller Programming Guide.
What I would do is to create a custom subclass of UINavigationController, and give it a (strong) property lastPoppedVC. Then override the implementation of popViewControllerAnimated to save the view controller that's being popped to the lastPoppedVC.
Also set up a swipe gesture recognizer for a slide-from-the-left gesture that pushes the lastPoppedVC back onto the stack. This would take some tinkering, as I don't think you could attach the gesture recognizer to the navigation controller's content view. You'd probably need to attach a gesture recognizer to every VC that you push onto your custom navigation controller's stack, and devise a way to trigger the "push back". (You might want to create a category of UIViewController that has a handleSwipeFromLeftGesture
method that sends a message to the owning navigation controller.)
The animation itself is no problem. Here's code where if you drag from the right another view controller's view comes in from the right. This is a tab bar controller, not a navigation controller, but the principles involved are absolutely the same:
https://github.com/mattneub/Programming-iOS-Book-Examples/blob/master/bk2ch06p296customAnimation2/ch19p620customAnimation1/AppDelegate.m
So the gesture of dragging from the right to bring in another view controller's view is perfectly straightforward.
The only problem is the question of interpreting what the drag from the right is supposed to mean logically. In the code I just pointed you to, it is clear what a drag from the left or right means: it means "switch to the view controller to the left / right of this one, if there is one" (in the tab bar controller) - and I have provided logic to make it do exactly that. Well, in the case of a navigation controller, it is clear what a drag from the left means: "go back". But I cannot imagine what view controller you expect is to be pushed onto the stack when the user drags from the right; you would have to provide logic to specify that somehow.
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