Hide tab bar on landscape mode - iphone

I am working on an app that uses tab bar for each view. (iphone app).
One of the view is a camera view where the user can take picture. Is there a way to hide the tab bar located bottom of the screen when the user changes to landscape mode? Then tab bar can reappear when it switches to portrait mode?
Thanks in advance.

Use the UIViewControllers delegate method: - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
It will get called everytime the orientation changes. A simple if statement should then check and decide when to set the tabbar hidden like so:
pseudo code:
if (toInterfaceOrientation == landscape)
[[self tabbarcontroller]tabbar sethidden:YES];
else
[[self tabbarcontroller]tabbar sethidden:NO];

if (toInterfaceOrientation == landscape)
self.tabBarController.tabBar.hidden = YES;
else
self.tabBarController.tabBar.hidden = NO;

Related

iOS UIInterfaceOrientation and UIDeviceOrientaion issue

I have one application in which a tab bar controller is having 3 tabs and each tab having a view controller.
View controller 1 and 2 are supporting only portrait mode but view controller in tab 3 supports all orientations -portrait, landscape left, landscape right and portrait upside down.
For tab 3, We have to show a particular view when device is in portrait mode and another view when device is in landscape mode.
If device is in portrait mode and user clicks on the tab 3, view is loaded correctly in portrait mode and then if we rotate the device to landscape mode the landscape view is loaded correctly.
But it we turn the device to landscape mode in the tab 1 itself and then click on the tab 3 , then the problem occurs then it shows the screen to be shown in landscape mode but it displays it as a portrait view.
When I tried to find out the reason for this in the delegate method by NSLogging
(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
the value of the interfaceOrientation is 1 which is UIInterfaceOrientationPortrait
and the control is going into the if condition written for the portrait mode
if(interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown){
and when I tried to print the value of UIDevice orientation in the same delegate method
UIDeviceOrientation interfaceOrientation = [UIDevice currentDevice].orientation;
NSLog(#" device orientation %u", interfaceOrientation);
the value printed in console is 4- which is UIDeviceOrientationLandscapeRight.
So the interface orientation is UIInterfaceOrientationPortrait but device orientation is UIDeviceOrientationLandscapeRight.
One more thing, now if I rotate the device to portrait mode and then moving to landscape mode shows the correct landscape view and app starts behaving correctly.
So the problem is if I load the tab 3 in landscape mode it doesn't load properly
but if we enter in portrait mode and then rotate to landscape if works fine from thereon.
If anyone can give some useful suggestion why the behavior is like this that would be really beneficial.
Thanks
Add these lines to your Tab1 & Tab2 in viewWillAppear method,
#import <objc/message.h>
- (void)viewWillAppear:(BOOL)animated {
if(UIDeviceOrientationIsLandscape(self.interfaceOrientation)){
if ([[UIDevice currentDevice] respondsToSelector:#selector(setOrientation:)]) {
objc_msgSend([UIDevice currentDevice], #selector(setOrientation:), UIInterfaceOrientationPortrait );
}
}
}
Create a CustomTabBarController Class with Subclass of UITabBarController (for e.g: CustomTabBarController)
#interface CustomTabBarController : UITabBarController
Add the following lines to this class :
- (BOOL)shouldAutorotate
{
return [self.selectedViewController shouldAutorotate];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
return [self.selectedViewController shouldAutorotateToInterfaceOrientation:toInterfaceOrientation];
}
- (NSUInteger)supportedInterfaceOrientations
{
return [self.selectedViewController supportedInterfaceOrientations];
}
In your app delegate or where ever you are initializing UITabBarController, replace those instances with CustomTabBarController instances.
self.tabBarController = [[[CustomTabBarController alloc] init] autorelease];
Add the lines to your model view controllers with different view controller support:
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationMaskPortrait;
}
-(BOOL)shouldAutorotate {
return NO;
}

Stop a modal UIViewController from rotating

The modal UIViewController's parent auto-rotates, but when the modal VC is up I only want it to appear in portrait and not be rotatable. I have tried simply returning NO from shouldAutorotate... in the modal VC, but no joy. Supporting iOS 5+.
Any help greatly appreciated.
Basically, if you presenting Modal Controller on Any Container Controllers (i.e. UINavigationController) it have autorotation method return YES by default. So you have to make subclass for your UINavigation Controller and Deprecate Autorotation there.
For iOS 5 use method:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
return (toInterfaceOrientation == UIInterfaceOrientationPortrait) : self.enableRotations;
}
for iOS 6:
- (NSUInteger)supportedInterfaceOrientations {
switch ([UIDevice currentDevice].userInterfaceIdiom) {
case UIUserInterfaceIdiomPad: return UIInterfaceOrientationMaskAll;
case UIUserInterfaceIdiomPhone: return UIInterfaceOrientationMaskPortrait;
}
}
- (BOOL)shouldAutorotate {
return NO;
}
It can be doable, but I would think twice before doing that.
As a user;
I launch the app and use in landscape.
trigger an event (eg. press button).
see a view which is portrait.
rotate the phone and look in portrait.
close the modal view.
get landscape view again.
need to rotate the phone again
Bad usability...
you have to present that new controller on a new navigation controller.This will solve your problem

Is it possible to have different orientations for viewControllers inside UINavigationController?

I want all view controllers to support only portrait mode, except one view controller lets call it "LandscapeSupportViewController" that should support also landscape mode.
The problem is when I'm in LandscapeSupportViewController in landscape mode and then push a new view controller that only support portrait mode, the pushed view controller will be in landscape mode also! How could I force it to be portrait?
I saw few apps that do it, take for example Skype iPhone app, the Messages tab is portrait only -> then if you press to enter the message itself you get a view controller that support landscape also because it make sense to enable landscape mode when user is chatting -> then if you press to view the persons profile, a new view controller will be pushed but in portrait! the same happen if you go back, you will forced to return to portrait even if you came from landscape...
Thanks
I'd had students try to accomplish exactly what you are trying to accomplish, and after much research, the general consensus is: this is a bad idea and requires a lot of (App Store legal) hacks to accomplish, and still doesn't turn out too pretty (status bar, for example, screws up). You'll notice in the Skype app that when you go into the IM section, rotate to landscape, and hit back, the UI "snaps", or sort of gets instantly reloaded.
This is not a good user experience, and I'd recommend rethinking your design to be more in line with what Apple recommends.
If i got you correctly you want to change device orientation in some conditions.
[[UIApplication sharedApplication] setStatusBarOrientation:UIDeviceOrientationPortrait animated:NO];
set your own orientation using above line, just put this lines inside the if condition. condition is depends on you.
Thank you!!
Write this lines before you push viewController which supported only portrait From landscapeViewController
[appdel.navigationController.view removeFromSuperview];// This navcontroller used with rootviewcontroller
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait];
[ [UIApplication sharedApplication].self.delegate.window addSubview:appdel.navigationController.view];
self.navigationController.navigationBar.hidden=NO;
Here is a solution.
You can add a category for UINavigationController which manages the view controller orientation. See code below:
#interface UINavigationController (MyViewOrientations)
#end
#implemetation UINavigationController (MyViewOrientations)
- (BOOL)supportLandscapeModeForViewController:(UIViewController *)controller {
return [controller isKindOfClass:[LandscapeSupportViewController class]]
}
- (NSUInteger)supportedInterfaceOrientation {
UIViewController *controller = [self visibleViewController];
NSUInteger orientationMasks = UIInterfaceOrientationMaskPortrait
if([self supportLandscapeModeForViewController:controller]) {
orientationMasks |= UIInterfaceOrientationMaskLandscapeLeft;
orientationMasks |= UIInterfaceOrientationMaskLandscapeRight;
}
return orientationMasks;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
UIViewController *controller = [self visibleViewController];
if([self supportLandscapeModeForViewController:controller]) {
return UIInterfaceOrientationLandscapeLeft; // Your call
}
else {
return UIInterfaceOrientationPortrait;
}
}
- (BOOL)shouldAutorotate {
UIViewController *controller = [self visibleViewController];
return [self supportLandscapeModeForViewController:controller];
}
#end
If the situation is more complex, different views support different orientations. You can override "supportedInterfaceOrientation", "preferredInterfaceOrientationForPresentation", "shouldAutorotate" in your view controllers, and delegate calls from UINavigationController category code with "visibleViewController".

UIViewController landscape mode buttons not working

I'm trying to get an app working in landscape mode which I've very nearly done, but for some reason the buttons on my view aren't working (ie. they don't press). I'm using a root view controller which loads the initial view controller as follows :
- (void)viewDidLoad
{
[super viewDidLoad];
StartViewController *viewController = [[StartViewController alloc] initWithNibName:#"StartView" bundle:nil];
self.startViewController = viewController;
startViewController.delegate = self;
[viewController release];
[self.view addSubview:startViewController.view];
}
I've also set the Initial Interface Orientation value in my Info.plist file and overridden the following in my root view controller :
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return((interfaceOrientation == UIInterfaceOrientationLandscapeRight) ||
(interfaceOrientation == UIInterfaceOrientationLandscapeLeft));
//return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
The view loads fine and fills the screen in landscape mode as it should, but for some reason I just can't press any of the buttons on the view.
I'm sure it's something simple related to me using a root view controller because I've managed to get this to work fine before with an app with just a single view controller.
Can anybody help me out here?
I think the problem is somewhere in xib.
E.g. the button is placed on UIView with incorrect resize masks. So that in landscape mode the button appears outside the view, and touches can't reach the button. You can check it setting clipSubviews in all the parent view -- if I'm right, you will not see the button any more.
I had a simular problem. In my case I was subclassing a UITableViewCell and I has overwritten the layoutSubviews method. In there I was doing translations. But I forgot to put the [super layoutSubviews]; before my implementation. After I put it htere, the button were working again in landscape mode. It was strange that in portrait it worked and in landscape not.

Iphone: Cannot switch back from my landscape view to a portrait view

I am working on an app (my first one), which is basically a TabBar app.
To be more precise there are:
- a login view controller
- a tab bar controller (when login is done)
- a landscape view controller that is used when the first itel of the TabBar is switch from Portrait to Landscape.
So, when I am in the first tab, I need to be able to move to landscape view to display some other data. In my tab bar controller, I have implemented those methods:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if([self selectedIndex] == 0)
return YES;
return NO;
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
[super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
// Get AppDelegate
MyAppDelegate *delegate = [[UIApplication sharedApplication] delegate];
if (toInterfaceOrientation == UIInterfaceOrientationLandscapeRight)
{
// Remove TabBarView and add graph Landscape View
[self.view removeFromSuperview];
[delegate setSubViewLandscapeViewController];
}
}
In the delegate, I have implemented the setSubViewLandscapeViewController and the setSubViewTabBarController:
- (void)setSubViewTabBarViewController {
[window addSubview:[tabBarController view]];
}
- (void)setSubViewGraphLandscapeViewController {
[window addSubview:[landscapeViewController view]];
}
I want the landscapeViewController to display only in landscape mode, I have then (in my landscapeViewController):
- (void)viewWillAppear:(BOOL)animated {
[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight];
}
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
NSLog(#"willRotateToInterfaceOrientation");
}
A part of this works fine, I mean the switch from portrait to landscape is ok (when I am in the first tab), the tabbarcontroller is remove from the SuperView and the landscape view is added as a subview instead.
The thing is... I do not know how to switch back to portrait mode (and then load the previous controller, the tabBar one using the setSubViewTabBarViewController of my delegate). It seems none of the willRotateToOrientation, willRotateFromOrientation, .. are triggered when I actually move the device from the landscape view...
In short, when I am in the landscape view I do not know what to do to move back to the tabbar view... I am kind of stuck in the landscape view once I am in this one.
Thanks a lot for your help,
Luc
Look at the pie chart in CPTestApp-iPhone in the examples folder. It handles rotation by implementing -(void)didRotateFromInterfaceOrientation: and resizing the graph after a rotation.
Well, I managed to get a solution for this problem.
In fact, while moving from portrait to landscape I removed the tabbarcontroller from window subview and add the landscapeviewcontroller instead.
It seems it was not the correct thing to do.
Instead, I add the landscapeViewController as subview of the tabbarcontroller and remove it when going from landscape to portrait.
I still have a problem however with the y position of the landscape view which seems to changes when I do several decive rotation in a row....
Regards,
Luc