Iphone Tabbar application not rotating - iphone

I created a tabbar application. First there were rotation enabled. The app did rotate without any difficulties. But for better usage i commented all auto rotation code and also in the infoplist deleted all other interface except portrait. But now i need it back. I uncommented all code and also added all interface orientation. But the application is not rotating. Please any one help me.Sorry for my bad english
Thanks
Rakesh

Every view controller added to tab bar controller will have
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return YES;
}
Make sure you return YES in each of them..

create a category like this and this method
#implementation UITabBarController(UITabBarControllerCategory)
-(BOOL)shouldAutorotateToInterfaceOrientation:
(UIInterfaceOrientation)toInterfaceOrientation
{
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication]delegate];
if ([AppDelegate isLandScapeOnly]){
return NO;
}
return YES;
}
#end

Related

Auto Rotate Dynamic UIViewcontroller

I have a scenario where I'm creating the UIViewcontrollers dynamically and adding a UIView on top of it and pushing it to the navigation stack. This is how I have created my view Controller
UIViewController *vc = [UIViewController new];
[vc.view addSubView:customView];
[self.navigationController pushViewController vc];
When running my App on the device, my view doesn't autorotate. (If the VC had a implementation file, I would have returned YES in shouldAutorotate to make it work.)
Any pointers/help is appreciated.
EdITed based on George's Reply:
George's code works perfectly for ios6 and above. supportedInterfaceOrientations API has been made available for ios6.0+, Looking for a general fix for ios4.3+
Thanks..
If your navigation controller is a rootviewcontroller than add this category to the place you created it, if it doesn't help that add to the viewcontroller which must rotate
#implementation UINavigationController(Rotate)
-(NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskAll;
}
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskAll;
}
#end
also may be your forgot to add in your app delegate
- (NSUInteger)supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
return UIInterfaceOrientationMaskAll;
}
Edit:
For iOS 5 you need only to add this method to needed viewcontroller.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
Try this delegate in your viewcontroller
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
return YES;
}

iOS6: supportedInterfaceOrientations not working (is invoked but the interface still rotates)

In my app I have multiple views, some views need to support both portrait and landscape, while other views need to support portrait only. Thus, in the project summary, I have all selected all orientations.
The below code worked to disable landscape mode on a given view controller prior to iOS 6:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
Since shouldAutorotateToInterfaceOrientation was deprecated in iOS6 I've replaced the above with:
-(NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMask.Portrait;
}
This method is correctly called when the view appears (I can set a breakpoint to ensure this), but the interface still rotates to landscape mode regardless of the fact that I'm returning the mask for portrait modes only. What am I doing wrong?
It seems that it's currently impossible to build an app that has different orientation requirements per view. It seems to only adhere to the orientations specified in the project summary.
If your are using a UINavigationController as the root window controller, it will be its shouldAutorotate & supportedInterfaceOrientations which would be called.
Idem if you are using a UITabBarController, and so on.
So the thing to do is to subclass your navigation/tabbar controller and override its shouldAutorotate & supportedInterfaceOrientations methods.
try change this code in AppDelegate.m
// self.window.rootViewController = self.navigationController;
[window setRootViewController:navigationController];
this is the complete answer
shouldAutorotateToInterfaceOrientation not being called in iOS 6
XD
In my case I have UINavigationController and my view controller inside. I had to subclass UINavigationController and, in order to support only Portrait, add this method:
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown;
}
So in the UINavigationController subclass I need to check which orientation is supported by the current topViewController.
- (NSUInteger)supportedInterfaceOrientations
{
return [[self topViewController] supportedInterfaceOrientations];
}
One thing I've found is if you have an old application that is still doing
[window addSubView:viewcontroller.view]; //This is bad in so may ways but I see it all the time...
You will need to update that to:
[window setRootViewController:viewcontroller]; //since iOS 4
Once you do this the orientation should begin to work again.
The best way for iOS6 specifically is noted in "iOS6 By Tutorials" by the Ray Wenderlich team - http://www.raywenderlich.com/ and is better than subclassing UINavigationController for most cases.
I'm using iOS6 with a storyboard that includes a UINavigationController set as the initial view controller.
//AppDelegate.m - this method is not available pre-iOS6 unfortunately
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
NSUInteger orientations = UIInterfaceOrientationMaskAllButUpsideDown;
if(self.window.rootViewController){
UIViewController *presentedViewController = [[(UINavigationController *)self.window.rootViewController viewControllers] lastObject];
orientations = [presentedViewController supportedInterfaceOrientations];
}
return orientations;
}
//MyViewController.m - return whatever orientations you want to support for each UIViewController
- (NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskPortrait;
}
As stated by others if you're using a UINavigationController and you want to customize various views you'll want to subclass the UINavigationController and make sure you have these two components:
#implementation CustomNavigationController
// -------------------------------------------------------------------------------
// supportedInterfaceOrientations:
// Overridden to return the supportedInterfaceOrientations of the view controller
// at the top of the navigation stack.
// By default, UIViewController (and thus, UINavigationController) always returns
// UIInterfaceOrientationMaskAllButUpsideDown when the app is run on an iPhone.
// -------------------------------------------------------------------------------
- (NSUInteger)supportedInterfaceOrientations
{
return [self.topViewController supportedInterfaceOrientations];
}
// -------------------------------------------------------------------------------
// shouldAutorotate
// Overridden to return the shouldAutorotate value of the view controller
// at the top of the navigation stack.
// By default, UIViewController (and thus, UINavigationController) always returns
// YES when the app is run on an iPhone.
// -------------------------------------------------------------------------------
- (BOOL)shouldAutorotate
{
return [self.topViewController shouldAutorotate];
}
Then in any view that is a portrait only you would include:
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
And in any view that is everything but upside down:
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAllButUpsideDown;
}
Basically as someone stated above, but in more detail:
Create a new file that is a subclass of UINavigationController
Go to your storyboard and then click on the Navigation Controller, set its class to the one that you just created
In this class(.m file) add the following code so it will remain in portrait mode:
(BOOL)shouldAutorotate
{
return NO;
}
(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
This worked for me
This code worked for me:
-(BOOL)shouldAutorotate {
return YES;
}
-(NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskAll;
}
iPhone/iPad App Orientation check out my own answer
The best way I think is to do a Category rather than subclassing UINavigationController or UITabbarController
your UINavigationController+Rotation.h
#import <UIKit/UIKit.h>
#interface UINavigationController (Rotation)
#end
your UINavigationController+Rotation.m
#import "UINavigationController+Rotation.h"
#implementation UINavigationController (Rotation)
-(BOOL)shouldAutorotate
{
return [[self.viewControllers lastObject] shouldAutorotate];
}
-(NSUInteger)supportedInterfaceOrientations
{
return [[self.viewControllers lastObject] supportedInterfaceOrientations];
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return [[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation];
}
#end
Try to make all your controller import this category and this work like a charm.
You can even make a controller not rotating and pushing another controller that will rotate.
Try add shouldAutorotate method
Firstly in order to make your app work in only mode you should be returning UIInterfaceOrientationMaskLandscape. In case you want to keep only portrait mode, you are doing things correctly.
Just add the UISupportedInterfaceOrientations key in the Info.plist and assign the interface orientation values your app intends to keep.
Also, you should be returning false from shouldAutoRotate in case you want to avoid auto rotation totally. But I would suggest you to return true from here and specify the correct orientations in supportedInterfaceOrientations method.
I have the same situation as you. I know you already accepted an answer, but I thought I'd add another one anyway. This is the way I understand the new version of the rotation system to work. The root view controller is the only view controller to ever be called. The reasoning, I believe, is that with child view controllers it doesn't make sense often to rotate their views since they will just stay within the frame of the root view controller anyway.
So, what happens. First shouldAutorotate is called on the root view controller. If NO is returned then everything stops. If YES is returned then the supportedInterfaceOrientations method is invoked. If the interface orientation is confirmed in this method and the global supported orientations from either the Info.plist or the application delegate, then the view will rotate. Before the rotation the shouldAutomaticallyForwardRotationMethods method is queried. If YES (the default), then all children will receive the will and didRotateTo... methods as well as the parent (and they in turn will forward it to their children).
My solution (until there is a more eloquent one) is to query the last child view controller during the supportedInterfaceOrientations method and return its value. This lets me rotate some areas while keeping others portrait only. I realize it is fragile, but I don't see another way that doesn't involve complicating things with event calls, callbacks, etc.
If you are using UINavigationController, you have to implement shouldAutorotate and supportedInterfaceOrientations in subclass of UINavigationController.
These are able to control by two steps, if shouldAutorotate returns YES then effective supportedInterfaceOrientations. It's a very nice combination.
This example, my mostly views are Portrait except CoverFlowView and PreviewView.
The CoverFlowView transfer to PreviewView, PreviewView wants to follow CoverFlowCView's rotation.
#implementation MyNavigationController
-(BOOL)shouldAutorotate
{
if ([[self.viewControllers lastObject] isKindOfClass:NSClassFromString(#"PreviewView")])
return NO;
else
return YES;
}
-(NSUInteger)supportedInterfaceOrientations
{
if ([[self.viewControllers lastObject] isKindOfClass:NSClassFromString(#"CoverFlowView")])
return UIInterfaceOrientationMaskAllButUpsideDown;
else
return UIInterfaceOrientationMaskPortrait;
}
...
#end
my solution : subclassed UINavigationController and set it as window.rootViewController
the top viewcontroller of the hierarchy will take control of the orientation , some code examples : subclassed UINavigationController
The answers here pointed me in the correct direction although I couldn't get it to work by just cut and pasting because I am using UINavigationControllers inside of a UITabBarController. So my version in AppDelegate.m looks something like this, which will work for UITabBarControllers, UINavigationControllers or UINavigationControllers within a UITabBarController. If you are using other custom containment controllers, you would need to add them here (which is kind of a bummer).
- (UIViewController*)terminalViewController:(UIViewController*)viewController
{
if ([viewController isKindOfClass:[UITabBarController class]])
{
viewController = [(UITabBarController*)viewController selectedViewController];
viewController = [self terminalViewController:viewController];
}
else if ([viewController isKindOfClass:[UINavigationController class]])
{
viewController = [[(UINavigationController*)viewController viewControllers] lastObject];
}
return viewController;
}
- (NSUInteger)application:(UIApplication *)application
supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
NSUInteger orientations = UIInterfaceOrientationMaskPortrait;
UIViewController* viewController = [self terminalViewController:window.rootViewController];
if (viewController)
orientations = [viewController supportedInterfaceOrientations];
return orientations;
}
Another key thing to note is that you must override supportedInterfaceOrientations in your UIViewController subclasses or it will default to what you specified in your Info.plist.

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".

iOS (iPhone/iPad) SDK - How to rotate an application from code (having troubles with UITabBarController)

In my App Delegate I overrode shouldAutorotateToInterfaceOrientation in my UITabBarController (don't worry - I didn't subclass it! ;) ) . I did it like this:
(Bottom of AppDelegate.h):
#interface UITabBarController (MyApp)
#end
(Bottom of AppDelegate.m):
#implementation UITabBarController (MyApp)
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
if(self.selectedIndex==4)
return (toInterfaceOrientation == UIInterfaceOrientationPortrait);
else
return (toInterfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
#end
Currently I have it so that when I go onto a specific tab (index 4), it will not rotate to landscape when the device is rotated (which is what I want). Although the problem is that if the application is already landscape and you tap onto that view, it is landscape (I want it to remain portrait). (NOTE: The app rotates fine if I let it to, so working with shouldAutorotateToInterfaceOrientation shouldn't really fix the problem (or it might))
I've found this UITabBarController delegate method:
- (void)tabBarController:(UITabBarController *)theTabBarController didSelectViewController:(UIViewController *)tabViewController {
NSUInteger indexOfTab = [theTabBarController.viewControllers indexOfObject:tabViewController];
if (indexOfTab == 4) {
//FILL GAP HERE!
}
}
I've tryed this:
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:YES];
But it only rotates the status bar - not the whole app. Is there some method (or anything) in UITabBarController that'll rotate it to portrait to fill in the gap above?
Sorry if it isn't too confusing for anyone.
Just implement shouldAutorotateToInterfaceOrientation:toInterfaceOrientation: for the view controller used in tab you dont want to rotate, and make sure it returns NO for the non-valid orientation(s).
Used transform and setStatusBarOrientation - although it has some side effects (will have to do for now).

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