First UIView in Portrait orientation and second in Landscape - iphone

I have an app which has 2 view controllers. The first viewcontroller should be in portrait and it's ok, but when I'm loading the second view controller, I could not make the app orientation to be landscape... The problem is with iOS 6.
I have tried everything I found on SO.
Using [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:NO]; on viewWillAppear and viewDidLoad,
and also:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if (interfaceOrientation == UIInterfaceOrientationPortrait) {
return (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
} else {
return (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
}
-(BOOL)shouldAutorotate
{
return YES;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationLandscapeRight;
}
-(NSInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskLandscapeRight;
}

Add these code in 2nd View Controller's viewDidLoad method to transform view into landscape :
[self rotateController:self degrees:-90];
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeLeft animated:NO];
//set it according to 3.5 and 4.0 inch screen in landscape mode
[self.view setBounds:CGRectMake(0, 0, 480, 320)];
add rotateController method :
-(void) rotateController:(UIViewController *)controller degrees:(NSInteger)aDgrees
{
UIScreen *screen = [UIScreen mainScreen];
if(aDgrees>0)
controller.view.bounds = CGRectMake(0, 0, screen.bounds.size.height, screen.bounds.size.width);
else
{
controller.view.bounds = CGRectMake(0, 0, screen.bounds.size.width, screen.bounds.size.height);
}
controller.view.transform = CGAffineTransformConcat(controller.view.transform, CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(aDgrees)));
}
Now in viewWillDisappear's method to transform view into protrait . Add these:
[self rotateController:self degrees:90];
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO];
//set it according to 3.5 and 4.0 inch screen in protrait mode
[self.view setBounds:CGRectMake(0, 0, 320, 480)];
Also your orientation methods should be like these if not added add these :
- (BOOL)shouldAutorotate
{
//make view landscape on start
return NO;
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscapeLeft;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationLandscapeLeft;
}
EDIT : Add these macro for radian
#define DEGREES_TO_RADIANS(angle) ((angle) / 180.0 * M_PI)

you may add this code on this view controller where you want to fix your orientation
Code as Below
-(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
if(UI_USER_INTERFACE_IDIOM()==UIUserInterfaceIdiomPhone)
{
return UIInterfaceOrientationMaskPortrait;
}
}
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
if(UI_USER_INTERFACE_IDIOM()==UIUserInterfaceIdiomPhone)
{
return (toInterfaceOrientation==UIInterfaceOrientationPortrait);
}
}
and second view controller you may want to rotate all orientation then not necessary to adding any code ios6 will manage the orientation automatically.

You need to select the landscape mode in application summary-> deployment info.
Also if you are using xib file to design the UI, you need to set the orientation of second view controller to landscape

-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
-(BOOL)shouldAutorotate
{
return NO;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationLandscapeRight;
}
-(NSInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscapeRight;
}
You were not returning the NO in the method shouldAutorotate , replace you existing code with this .
Hope it will help you.

Prior to iOS 6 i.e in iOS 5 and earlier, an app and a view controller’s rotation is controlled by the individual viewcontrollers while in iOS 6 and later, the view controllers responsible for rotation are the container Viewcontrollers such as UINavigationController & UITabBarController . What are you using as the rootviewcontroller in your project??
Autorotation is clearly explained here in this post- Autorotation in iOS

Related

Force landscape for one view controller ios

I've looked at several answers to questions similar but none of the answer worked. I have an app where I need everything portait except for one photo viewer I have. In the supported orientations section of the targets menu I only have portrait. How do I force my one view to be landscape. It is being pushed onto the stack from a nav controller but I'm using storyboards to control all that.
Since the answer seems to be hidden in the comments of the question and since ArunMak's answer is quite confusing, I'll just offer what I found out:
All I had to do was to add this function to my custom UIViewController subclass for the view:
- (NSUInteger)supportedInterfaceOrientations {
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
// iPad: Allow all orientations
return UIInterfaceOrientationMaskAll;
} else {
// iPhone: Allow only landscape
return UIInterfaceOrientationMaskLandscape;
}
}
Note that the project needs to allow all orientations (that is: Portrait, Landscape Left, Landscape Right - but NEVER Upside Down on an iPhone!).
If you want to limit some or most views to Portrait, you need to implement the above method in every of those view controllers (or use a common super class for it and subclass all others from it) — if you limit the Device Orientation in the Info.plist to just Portrait, the app will never even think of going into landscape.
Yes this is possible, you can use this code:
-(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
return UIInterfaceOrientationMaskLandscape;
}
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orientation {
return orientation==UIInterfaceOrientationMaskLandscape;
}
OR
Try this method in your app delegate
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
if (sglobalorientation isEqualToString:#"AllOrientation"]) {
return UIInterfaceOrientationMaskLandscape;
} else {
return UIInterfaceOrientationMaskAll;
}
}
you need to change the variable value sglobalorientation to that string value AllOrientation before you move to that Landscape view controller
and in your Landscape view controller, use this code in your view will appear
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeLeft];
DigitalSignatureViewController *digisign = [[DigitalSignatureViewController alloc]init];
[self presentModalViewController:digisign animated:NO];
[self dismissModalViewControllerAnimated:NO];
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return NO;
}
and again when you move to next view controller change the sglobalorientation string value and follow the same step in your next view controller.
Lets try this code:
[UIApplication sharedApplication].statusBarOrientation = UIInterfaceOrientationLandscapeRight;
self.navigationController.view.center = CGPointMake(([UIScreen mainScreen].bounds.size.width/2), [UIScreen mainScreen].bounds.size.height/2);
CGFloat angle = 90 * M_PI / 180;
self.navigationController.view.transform = CGAffineTransformMakeRotation(angle);
self.navigationController.view.bounds = CGRectMake(0, 0,[UIScreen mainScreen].bounds.size.height , [UIScreen mainScreen].bounds.size.width);

Force portrait in one view controller makes other to be in portrait initially

The root view controller of navigation controller supports only portrait orientation and other controllers supports all orientation.Now if i am on the root view controller and the DEVICES is in landscape and if i push next view controller that opens in portrait that should open in landscape as it supports all orientation.
Please help me with this.
Using iPhone 4s iOS6.1.3
you can check Device orientation in your first screen after login viewcontroller using bellow code:-
-(void)viewWillAppear:(BOOL)animated
{
[self willRotateToOrientation:[[UIDevice currentDevice] orientation]];
[super viewWillAppear:YES];
}
- (void)willRotateToOrientation:(UIInterfaceOrientation)newOrientation {
if (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation))
{
if (newOrientation == UIInterfaceOrientationLandscapeLeft || newOrientation == UIInterfaceOrientationLandscapeRight) {
//set your landscap View Frame
[self supportedInterfaceOrientations];
}
}
else if (UIDeviceOrientationIsPortrait([UIDevice currentDevice].orientation))
{
if(newOrientation == UIInterfaceOrientationPortrait || newOrientation == UIInterfaceOrientationPortraitUpsideDown){
//set your Potrait View Frame
[self supportedInterfaceOrientations];
}
}
// Handle rotation
}
sor when you load this viewcontroller it check first device oriantation and then load it's related frame
I think this is the issue related to the orientation changes in iOS6. You need to subclass the UINavigationController
Check this
1 . You have to create sub class of UINavigationController. add Following method.. Take one boolean variable to check whether it support for all orientation or not and change its value.
#implementation NavigationControllerViewController
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
AppDelegate *appdelgate=[[UIApplication sharedApplication]delegate];
if (appdelgate.issuppoertAll) {
// for iPhone, you could also return UIInterfaceOrientationMaskAllButUpsideDown
return UIInterfaceOrientationMaskAll;
}
return UIInterfaceOrientationMaskPortrait;
}
#end
2 when you navigate form root view controller to other view controller
use this code , when you want to forcefully change its orientation.i.e lanscape to portrait
obj_viewcontroller = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
[self presentModalViewController:obj_viewcontroller animated:NO];
[self dismissModalViewControllerAnimated:NO];
[self.navigationController pushViewController:obj_viewcontroller animated:NO];
3 In second view controller you have to change boolean variable value
-(void)viewWillAppear:(BOOL)animated
{
appdelgate.issuppoertAll=YES;
}
4 Add this method into all view controller and set orientation as per your need.
- (NSInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}

ios 6 orientation methods

the orientation methods have changed in iOS 6.
my whole app in portrait mode got to many view controllers (not tab bar view controllers) i just want to rotate one of my view controller to landscape mode (it actually displays a webView) when i rotate the device.the below method was working in xcode 4.4 but, it's not in Xcode.4.5
- (BOOL)shouldAutorotateToInterfaceOrientation:
(UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationPortrait ||
interfaceOrientation == UIInterfaceOrientationLandscapeLeft ||
interfaceOrientation == UIInterfaceOrientationLandscapeRight );
the above method won't work in xcode 4.5 for this reason i have changed the below method but even though its not working....plz any suggestions thanks.
- (BOOL) shouldAutorotate{
[[UIApplication sharedApplication] setStatusBarOrientation: UIInterfaceOrientationPortrait];
return self.modalViewController.shouldAutorotate;
}
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscape;
}
Do you use tab bar view controller? If you use it, then all view controllers in all tabs should be able to rotate even if you only want to rotate only one.
-(NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskPortrait;
}
This should work fine in iOS6.
If you use UINavigationViewController, then its methods would be called. There is another solution.
// App delegate.m
- (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;
}
And then in view controllers
- (NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskPortrait;
}

Alternate landscape triggered at unwanted view

I have a view controller that contains an image and a tableview. From this view controller I connected a segue to a landscape view that contains the image in full screen (same idea used when you turn sideways the Stocks app from Apple to see the graph in full screen).
This segue is called by the following method:
- (void)updateLandscapeView
{
UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
if (UIDeviceOrientationIsLandscape(deviceOrientation) && !isShowingLandscapeView)
{
[self performSegueWithIdentifier: #"toGraph" sender: self];
isShowingLandscapeView = YES;
}
else if (deviceOrientation == UIDeviceOrientationPortrait && isShowingLandscapeView)
{
[self dismissViewControllerAnimated:YES completion:nil];
isShowingLandscapeView = NO;
}
}
Besides this, when the iphone is at portrait orientation, I can also drill-down the tableview a couple more levels. The problem is the following: at those consequent levels, the segue to the landscape view still gets triggered when I turn the orientation to landscape!... what can I do so that this does not happen? I am only interested in going to landscape mode from the first view which contains the image.
Thank You in advance!
I don't know for sure if I got your issue right.. but if you mean with "drill-down the table view" to go deeper in a navigation controller hierachy, you can try the following..
That's what I did in a (I think) similar situation:
AppDelegate:
in .h:
#property (nonatomic) BOOL shouldAutorotate;
in .m:
// in didFinishLaunchingWithOptions:
self.shouldAutorotate = NO;
// still in .m file
// Autorotation handling
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
return self.shouldAutorotate ?
UIInterfaceOrientationMaskAllButUpsideDown :
UIInterfaceOrientationMaskPortrait;
}
Navigation Controller presenting Portrait Controller
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (NSUInteger)supportedInterfaceOrientations
{
if (self.selectedViewController)
return [self.selectedViewController supportedInterfaceOrientations];
return UIInterfaceOrientationMaskPortrait;
}
- (BOOL)shouldAutorotate
{
return YES;
}
Portrait View Controller (here's also a very similar segue handling that you have):
in viewWillAppear:
[(AppDelegate *)[[UIApplication sharedApplication] delegate] setShouldAutorotate:YES];
rotation handling:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (BOOL)shouldAutorotate
{
return NO;
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
Landscape View Controller (probably your full screen image):
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscape;
}
Deeper in the navigation controller hierachy (where only portrait is wanted):
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (BOOL)shouldAutorotate
{
return NO;
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
Looks somehow complicated, but that was the only way, I managed to get those rotation things working properly in both iOS5 and 6.

setStatusBarOrientation issue

I have a navigation controller app. And first I push FirstViewController (support Portrait orientation) and then SecondViewController (supports all orientations). When I'm in landscape mode of SecondViewController and press back button, FirstViewController appears in landscape mode. That's why I manually rotate the navigation view, but when I want to set setStatusBarOrientation to Portrait (First view controller should appears only in portrait mode), the orientation of view controller is still landscape, and even if rotate the device to portrait mode, the orientation stay landscape
.Here is my code of FirstViewController:
- (void)viewWillAppear:(BOOL)animated
{
if (UIInterfaceOrientationIsLandscape(self.interfaceOrientation))
{
if (self.interfaceOrientation == UIInterfaceOrientationLandscapeLeft) {
prevInterfaceOrientation = UIInterfaceOrientationLandscapeLeft;
self.navigationController.view.transform = CGAffineTransformIdentity;
self.navigationController.view.transform =
CGAffineTransformMakeRotation(degreesToRadians(90));
}
else if (self.interfaceOrientation ==
UIInterfaceOrientationLandscapeRight) {
prevInterfaceOrientation = UIInterfaceOrientationLandscapeRight;
self.navigationController.view.transform = CGAffineTransformIdentity;
self.navigationController.view.transform =
CGAffineTransformMakeRotation(degreesToRadians(-90));
}
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO];
[self.tableViewDetail reloadData];
}
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
if (toInterfaceOrientation == UIInterfaceOrientationPortrait)
{
if (prevInterfaceOrientation == UIInterfaceOrientationLandscapeLeft) {
self.navigationController.view.transform = CGAffineTransformIdentity;
}
else if (prevInterfaceOrientation ==
UIInterfaceOrientationLandscapeRight) {
self.navigationController.view.transform = CGAffineTransformIdentity;
}
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait];
[self.tableViewDetail reloadData];
}
}
I even tried to use:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
if (UIInterfaceOrientationIsLandscape(prevInterfaceOrientation))
{
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait];
}
}
but self.interfaceOrientation still stays landscape, when I rotate to portrait.
But I really need to rotate the view to portrait mode manually to allow users to see,that FirstViewController suppors only portrait orientation.
I have the option to put the SecondViewController's view on MainWindow (like modal window), but I don't like this idea, because if apple has setStatusBarOrientation method, it seems to me, that it has to be right solve of this issue.
I would get rid of the transformations, and use
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:animated];
This in combination with the forced redrawing of the view stack will get it done. This can be done by adding the following to viewDidAppear to the first controller (it doesn't work in viewWillApear).
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
UIWindow *window = [[UIApplication sharedApplication] keyWindow];
if ([window.subviews count] > 0) {
UIView *view = [window.subviews objectAtIndex:0];
[view removeFromSuperview];
[window insertSubview:view atIndex:0];
}
else {
DLog(#"NO view to force rotate?");
}
Unfortunately, the transition animation is not very clean when you do this, so I would recommend taking a snapshot of the portrait screen, overlay this over your view, and then fade it out with a separate animation.
Steven Veltema's answer didn't work for me.
I had one view controller where all orientations where allowed, and the rest only supported portrait. When i had the first view controller in landscape and navigated to another view controller, the orientation didn't refresh as you are experiencing.
I found another trick to reload the views i correct orientation. Just add a modal view controller you don't even see it. Add this in all other views:
- (void)viewDidAppear:(BOOL)animated
{
UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];
if(UIInterfaceOrientationIsLandscape(interfaceOrientation)){
UIViewController * viewController = [[UIViewController alloc] init];
[self presentModalViewController:viewController animated:NO];
[viewController dismissModalViewControllerAnimated:NO];
}
[super viewDidAppear:animated];
....
}
Another quick solution is
Click on your project in the left side bar.
In General settings, choose "Hide during application launch" option.