This question has been asked a lot e.g. here but as far as I can see is yet to be answered in full.
I have a UITabBarController
with a UINavigationController
as the root vc for one of the tabs, which itself has a MKMapView
as its root vc. The behaviour I want is for the map to partially curl upwards, while leaving the tab bar in place (similar to the Maps app).
So far all I have managed to get working is for the whole view to curl, which isn't as nice.
Solutions I have seen are to set the hidesBottomBarWhenPushed
property to NO, which would make sense however this doesn't seem to work, (unless I am doing something wrong).
For clarity, my code is as follows:
MyVC *aView = [MyVC init];
aView.modalTransitionStyle = UIModalTransitionStylePartialCurl;
aView.hidesBottomBarWhenPushed = NO;
For the presenting part, I have tried the two alternatives below, neither of which seem to work:
[self presentModalViewController:updateStatus animated:YES];
[[self navigationController] presentModalViewController:updateStatus animated:YES];
Any help much appreciated.
Tim Arnold's response worked great for me, thanks!
One trap to watch out for: your modal page-curl transition will take over the whole screen if your content view controller is added as a child of the container view controller. You could just not add it as a child, but then none of the view lifecycle methods will get called on your content controller (e.g.
viewDidLoad
,viewWillAppear
), which could be a problem.Fortunately, there is a way around this. In your container controller:
viewDidLoad
viewDidAppear
viewWillDisappear
.That way, your content controller gets its lifecycle methods called, while still being able to do a modal page-curl transition without taking up the whole screen.
Here is the entire code of a bare-bones solution:
I've scoured StackOverflow (and the Internet) for a solution to this problem. The question has been asked many times, but as you note, never sufficiently answered. Many solutions give an acceptable solution if it is unimportant whether, e.g., a lower toolbar curls up as well.
Others have provided a solution using
UIView
animations / CoreAnimation rather thanUIModalTransitionStylePartialCurl
as a modal transition style; this is at worst a solution not allowed in the App Store, and at best is not quite the same effect as one gets fromUIModalTransitionStylePartialCurl
(e.g. the shape of the curl is different).None of these solutions have provided an answer that mimics Apple's solution in the Maps app (i.e., using
UIModalTransitionStylePartialCurl
but leaving an un-curledUIToolbar
at the bottom of the screen).I will continue in this tradition of incomplete answers, since you ask about a
UITabBarController
and my solution doesn't specifically address that case. It does, however, solve the problem I had, which was to get a half page curl with an un-curled toolbar at the bottom.There must be a more elegant way to do this, but this is how I managed.
The
rootViewController
of myAppDelegate
is a subclass ofUIViewController
, which I'll callTAContainerViewController
.TAContainerViewController
manages a) the actual contents of the screen (the "stuff to be curled"),TAContentViewController
, and b) the contents "behind" theTAContentViewController
(e.g. settings), which I'll callTAUnderCurlViewController
.My instance of
TAContainerViewController
had properties for aTAContentViewController
and aTAUnderCurlViewController
. TheUIView
that was my content was a subview ofTAContentViewController
'sview
property; likewise what the user sees under the curl is theview
property of theTAUnderCurlViewController
.In the
init
method ofTAContainerViewController
I make sure to do the following:And to curl the contents to reveal under the page, I set up an action that calls this code:
where
self
is theTAContainerViewController
,contentVC
is an instance ofTAContentViewController
, andunderCurlVC
is an instance ofTAUnderCurlViewController
.To dismiss the view, simply
[self.contentVC dismissModalViewControllerAnimated:YES];
.Some strangeness seems to occur with the frame of
contentVC
when the modal view is dismissed, so I manually reset the frame when the modal view is dismissed.I've posted a sample project with more details on Github. Hopefully someone can take this and turn it into a slightly more elegant solution, or expand it to work with a
UINavigationController
orUITabBarController
. I think the trick is to pull the View Controllers out of the well-defined relationships in the Cocoa subclasses, so maybe subclassing those specialty View Controllers would do it.