So here is what i have:
A UITabBarController that handles different UIViewControllers. In one of the UIViewController i am trying to switch the view being displayed when the device rotates to landscape.
the important part is that the view displayed in landscape MUST take the whole screen...
I have correctly implemented the methods :
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
In fact i do have my rotation occurring correctly, and I my views swaped.
i even hide status bar, nav bar and Tab bar BUT i keep having a blank space at the bottom of the screen which is the place of the TabBar...
So i am assuming that setting the hidden property of the tabBar is not enough in order to have the view on the whole screen. I think there is some stuff to do within the TabBarController or even the MainWindow to say somehting like "i don't need TabBarController now". But i do not see how to get around this problem properly.
If anyone has been around this issue, i would appreciate some help.
thank you,
Sami.
This worked for me.
- (void)viewDidLoad {
[super viewDidLoad];
previousRect = self.view.frame;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration;
{
if(toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft || toInterfaceOrientation == UIInterfaceOrientationLandscapeRight) {
[self.navigationController setNavigationBarHidden:TRUE animated:FALSE];
[[UIApplication sharedApplication] setStatusBarHidden:TRUE animated:FALSE];
}
else
{
[self.navigationController setNavigationBarHidden:FALSE animated:FALSE];
[[UIApplication sharedApplication] setStatusBarHidden:FALSE animated:FALSE];
}
}
-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
UIInterfaceOrientation toOrientation = self.interfaceOrientation;
if ( self.tabBarController.view.subviews.count >= 2 )
{
UIView *transView = [self.tabBarController.view.subviews objectAtIndex:0];
UIView *tabBar = [self.tabBarController.view.subviews objectAtIndex:1];
if(toOrientation == UIInterfaceOrientationLandscapeLeft || toOrientation == UIInterfaceOrientationLandscapeRight) {
transView.frame = CGRectMake(0, 0, 480, 320 );
tabBar.hidden = TRUE;
}
else
{
transView.frame = previousRect;
tabBar.hidden = FALSE;
}
}
}
This code works fine but when i dismiss a uiviewcontroller which is presented modally, my view is under the status bar by 20 pixel.
My view is inside a navigationcontroller so i do not hide it before rotation.
I needed tab bar to go into full screen mode in landscape view and I tried the approach suggested above using
transView.frame = CGRectMake(0, 0, 480, 320 );
This turned out to be a hacky solution and posed many problems such as with hiding and re-displaying the status bar (the view would overlap with the status bar when it is re-displayed after exiting portrait view). I would not recommend this. What worked for me perfectly in the end was pushing a new view controller containing the landscape view and using delegation to reuse the functionality of the original VC.
This approach is working for me:
- (void) willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
UIView *parentView = self.tabBarController.view;
CGRect frame = parentView.frame;
CGFloat windowHeight = parentView.window.frame.size.height;
switch (toInterfaceOrientation) {
case UIInterfaceOrientationLandscapeLeft:
case UIInterfaceOrientationLandscapeRight:
CGFloat tabBarHeight = self.tabBarController.tabBar.frame.size.height;
frame.size.height = windowHeight + tabBarHeight;
break;
default:
frame.size.height = windowHeight;
break;
}
[UIView animateWithDuration:duration animations:^{
parentView.frame = frame;
}];
}
(Only tested in iOS8.)
Subclass your TabBarController and hide the TabBar when needed:
class tabBarVC: UITabBarController {
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
if size.height < size.width {
self.tabBar.hidden = true
} else {
self.tabBar.hidden = false
}
}
}
Maybe you want to use this
- (void)willAnimateRotationToInterfaceOrientation:UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
[super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
__block UIView *weakTabBar = [self.tabBarController.view.subviews objectAtIndex:1];
weakTabBar.alpha = 0;
[UIView animateWithDuration:duration
delay:0
options:UIViewAnimationOptionCurveEaseIn // slow at the beggining
animations:^{
weakTabBar.alpha = 1;
}
completion:^(BOOL finished) {
weakTabBar.alpha = 1;
}];
}
}
This doesn't hide the tab bar but makes the rotate animation smoother.
If you have your UITabBarController then put a UINavigationController inside it then you can use hidesBottomBarWhenPushed (with a bit of trickery) to do this.
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
[super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
if (toInterfaceOrientation == UIInterfaceOrientationPortrait) {
self.hidesBottomBarWhenPushed = NO;
self.navigationController.viewControllers = self.navigationController.viewControllers;
[self transitionToGridLayout];
}
else {
self.hidesBottomBarWhenPushed = YES;
self.navigationController.viewControllers = self.navigationController.viewControllers;
[self transitionToCoverflowLayout];
}
}
The trick is to push your view controller so that the hidesBottomBarWhenPushed
flag is picked up. You can use following.
self.navigationController.viewControllers = self.navigationController.viewControllers;