I am building an application that is for iOS6+. The application will have a main View Controller at one point in the application.
I would like this main view controller
What you are looking to do sounds a lot like the iPhone version of Apple's UIPageControl Demo;
Sounds like a job for UISwipeGestureRecognizer.
My favorite side-drawer controller: https://github.com/mutualmobile/MMDrawerController
MMDrawerController is highly configurable and does all the things you mention:
If you're using a storyboard you can use this extension to have storyboard support: https://github.com/TomSwift/MMDrawerController-Storyboard
EDIT:
Another option might be to use a UIPageViewController
with a transition style of UIPageViewControllerTransitionStyleScroll
: https://developer.apple.com/library/ios/documentation/uikit/reference/UIPageViewControllerClassReferenceClassRef/UIPageViewControllerClassReference.html
This will have the behavior of "pulling" in the side view controllers vs. "uncovering" them.
EDIT 2: example per request
The only real complicating requirement you have is that the same view controller is used for both left and right. That means we have to track where the view controller is being presented so that we can correctly manage our data source. Without this requirement we could just back our data source with an array and derive next/prev from that.
First, the storyboard. The storyboard has three view controllers: 1) the UIPageViewController
, which I've subclassed as TSPageViewController
. Don't forget to set the page controller transition-style property to 'scroll'. 2) the "center" view controller, and 3) the "side" view controller. For center and side I've set the storyboard ID of each to "center" and "side", respectively. For this sample, both the center and side controllers are plain vanilla UIViewControllers
, and I've set their view backgroundColor
's to tell them apart.
Second, the page view controller:
.h
@interface TSPageViewController : UIPageViewController
@end
.m
@interface TSPageViewController () <UIPageViewControllerDataSource>
@end
@implementation TSPageViewController
{
UIViewController* _side;
UIViewController* _center;
}
- (void) viewDidLoad
{
[super viewDidLoad];
self.dataSource = self;
_side = [self.storyboard instantiateViewControllerWithIdentifier: @"side"];
_center = [self.storyboard instantiateViewControllerWithIdentifier: @"center"];
[self setViewControllers: @[_center]
direction: UIPageViewControllerNavigationDirectionForward
animated: NO
completion: nil];
}
- (UIViewController*) pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
if ( viewController == _center )
{
_side.title = @"right";
return _side;
}
if ( viewController == _side && [_side.title isEqualToString: @"left"] )
{
return _center;
}
return nil;
}
- (UIViewController*) pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
if ( viewController == _center )
{
_side.title = @"left";
return _side;
}
if ( viewController == _side && [_side.title isEqualToString: @"right"] )
{
return _center;
}
return nil;
}
@end
Again, the only thing here that's special is the tracking of the whether the side controller is currently "left" or "right". This implementation has an issue in that it relies on the behavior of the UIPageViewController to not "page ahead" and cache view controllers (if it did, our logic would get confused). So you might want to consider a more robust mechanism to track which side the view controller is currently on. For that you'd likely have to introduce your own swipe gesture recognizer and use the data from that to drive tracking left/right.
If you can toss your requirement of using the same view controller for left and right, then you can have separate left/right/center controllers, stored in an array, and return next/prev controllers based on what you see in the array. Much easier and more robust!
for iOS6+:
I'd be inclined to use https://github.com/pkluz/PKRevealController and just set both left and right viewControllers to be pointers to a single viewController.
for iOS7+:
I think you should be looking into custom UIViewController transitions.
https://github.com/ColinEberhardt/VCTransitionsLibrary
http://www.teehanlax.com/blog/custom-uiviewcontroller-transitions/
There is a good WWDC 2013 video on this subject entitled "Custom transitions using view controllers", it's session 218.
You can accomplish that with some of the cocoa controls such as:
https://github.com/Inferis/ViewDeck
https://github.com/gotosleep/JASidePanels
EDIT: Proposal number two, use a controller with a scrollView:
// Allocate all the controlelrs you need
MyFirstViewController *first = [[MyFirstViewController alloc] init];
MySecondViewController *second= [[MySecondViewController alloc] init];
MyThirdViewController *third = [[MyThirdViewController alloc] init];
// Adjust the frames of the controllers
first.view.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
second.view.frame = CGRectMake(0, self.view.frame.size.width, self.view.frame.size.width, self.view.frame.size.height);
third .view.frame = CGRectMake(0, 2 * self.view.frame.size.width, self.view.frame.size.width, self.view.frame.size.height);
// Add controllers as subViews to the scrollView
[self.scrollView addSubview:self.first.view];
[self.scrollView addSubview:self.second.view];
[self.scrollView addSubview:self.third.view];
// Set the scrollView contentSize and paging
self.scrollView.contentSize = CGRectMake(self.view.frame.size.width * 3, self.view.frame.size.height);
self.scrollView.pagingEnabled = YES;
// Scroll to the middle view initally
[self.scrollView scrollRectToVisible:CGRectMake(0, self.view.frame.size.width, self.view.frame.size.width, self.view.frame.size.height) animated:NO];
The code above is written by heart, I have probably named a few things wrongly, and there is more than one way to handle the subviews. The mentioned pageViewController in the comments will work as well.