Using interface builder in xcode and just one .xib file, how can I create alternate layouts when rotating between landscape and portrait orientations?
See di
Solution with storyboard [ios7]. Inside the main view controller, there is the container view that can include the tab bar controller. Inside the tab bar controller, there are 2 tabs. One tab is for controller with portrait and another is for controller in landscape mode.
The main view controller implements these functions:
#define INTERFACE_ORIENTATION() ([[UIApplication sharedApplication]statusBarOrientation])
@interface MainViewController ()
@property(nonatomic,weak) UITabBarController *embeddedTabBarController;
@end
@implementation MainViewController
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:@"embedContainer"])
{
self.embeddedTabBarController = segue.destinationViewController;
[self.embeddedTabBarController.tabBar setHidden:YES];
}
}
- (void) adaptToOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if (UIInterfaceOrientationIsLandscape(interfaceOrientation))
{
[self.embeddedTabBarController setSelectedIndex:1];
}
else
{
[self.embeddedTabBarController setSelectedIndex:0];
}
}
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration
{
[self adaptToOrientation:interfaceOrientation];
}
- (void) viewWillAppear:(BOOL)animated
{
[self adaptToOrientation:INTERFACE_ORIENTATION()];
}
The segue link in storyboard should be named "embedContainer".
Assure that container view is resizable to fulfil the parent view, in both cases, landscape and portrait.
Take care about the fact that in the runtime 2 instances of the same controller lives in the same time.
Update: Apple docs for alternate landscape view controller
A way to do this is to have three views in your .xib file. The first one is the normal view of your Viewcontroller with no subviews.
Then you create the views for portrait and landscape as you need them. All three have to be root-level views (have a look at the screenshot)
In your Viewcontroller, create 2 IBOutlets, one for the portrait and one for the landscape view and connect them with the corresponding views in the interface builder:
IBOutlet UIView *_portraitView;
IBOutlet UIView *_landscapeView;
UIView *_currentView;
The third view, _currentView
is needed to keep track of which one of these views is currently being displayed.
Then create a new function like this:
-(void)setUpViewForOrientation:(UIInterfaceOrientation)orientation
{
[_currentView removeFromSuperview];
if(UIInterfaceOrientationIsLandscape(orientation))
{
[self.view addSubview:_landscapeView];
_currentView = _landscapeView;
}
else
{
[self.view addSubview:_portraitView];
_currentView = _portraitView;
}
}
You will need to call this function from two different places, first for initialization:
-(void)viewDidLoad
{
[super viewDidLoad];
UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];
[self setUpViewForOrientation:interfaceOrientation];
}
And second for orientation changes:
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
[self setUpViewForOrientation:toInterfaceOrientation];
}
Hope that helps you!