Force portrait orientation on pushing new view to UINavigationViewController - iphone

I have a TabBar bases application, which supports Landscape orientation only for one special view (the rootview of a UINaviagtionController). Now i want to force portrait orientation for all other views for this navigationcontroller.
I have tried to use
[[UIDevice currentDevice] setOrientation:UIDeviceOrientationPortrait];
This works great but this piece of code is a private api call and I can not risk a app rejection.
I have also tried to rotate the next view manually but this rotates only the view and not the navigation or the tab bar.
Is there a similary way to force orientation change?

There is currently no way to do that.
Have a look at this question, I have the same problems. With a tabbar application, you must have everything to autorotate, or nothing. You can find ways to have shouldAutorotate answer differently on each view, but actually this does not work. I don't know if this is an intended behaviour or a bug, anyway the only viable solution I'm aware of (without using undocumented API) is to manage the rotation by yourself, and do not rely on autorotation.
This means in other words that you need to start orientation notifications (look at UIDevice, there are methods to start and stop notifications about the device orientation), then for each view you want to rotate register as observer, and manage orientation manually, like this (don't remember where I got this snippet):
// Rotates the view.
CGAffineTransform transform = CGAffineTransformMakeRotation(M_PI/2);
self.view.transform = transform;

Related

Flip the iPhone screen with a button

how do I implement a button that will flip the screen 180deg for my game (if the user wishes to play it with the iPhone upside-down), and have it affect all of my 5 different views?
You should apply a transform to the parent view (your UIWindow). The rotation can be made using CGAffineTransformMakeRotation().
It might be better to actually allow the device orientation to cause the rotation though. In App settings set that the app supports autorotation and then in the UIViewController return tru to -(BOOL)shouldAutorotateToInterfaceOrientation when the rotation passed in is UIInterfaceOrientationPortraitUpsideDown
Look at shouldAutorotateToInterfaceOrientation. And maybe [myView setNeedsDisplay]; could help.
It sounds like you just want to use the build in automatic orientation rotation. You may need to tell your app in the build settings that it supports the upsidedown orientation and as dasdom mentioned you need to implement shouldAutorotateToInterfaceOrientation in all of your view controllers.
There is no way to force the phone into an orientation on-demand.
If you are looking to just rotate a view you can apply a CGAffineTransform.

UiViewController rotation question

I have main menu in my app supporting only landscape mode.
I implement landscape restriction by setting up UIRootViewController::shouldAutorotateToInterfaceOrientation:...
And I have another scene with portrait mode support.
So the problem appears when I pass from another scene to main menu in portrait mode: the app doesn't rotate to landscape automatically, and I can't find a code method to manually rotate it.
Is there a solution? Would be thankful.
Edit: Excuse me, I forgot to add details. RootViewController is common for menu and another scene. And what is more - these scenes are in one common view (my app uses OpenGL)
So before I enter menu from portrait scene I set UIRootViewController::shouldAutorotateToInterfaceOrientation: to return YES for landscape only.
If your other scene with portrait support is controlled by another UIViewController, then you can use that view controller's -shouldAutorotateToInterfaceOrientation: to define its behavior. In many cases, this alone should be enough. Of course, if you need to do some fancy rotations for some view controller but not for others, then things get a bit trickier.
There is no easy way to do this, except [UIDevice setOrientation:], which is not open to developers, and leads to application rejection by Apple.
You can apply a rotation to your layer which will create the exact same effect.
myview.layer.transform = CATransform3DMakeRotation(M_PI/2, 0.0f, 0.0f, 1.0f);

iPhone rotation woes

I have been spending many frustrating hours trying to get rotations working on the iPhone version of Tunepal.
Firstly, I have a tab bar controller, with a navigation controller controlling each of the views.
I actually only want one of my views to be able to rotate and that is the TuneDisplay.
I have a subclassed the UITabBarController and overridden the shouldAutorotateToInterfaceOrientation:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation) interfaceOrientation {
if (self.selectedViewController != nil)
{
return [self.selectedViewController shouldAutorotateToInterfaceOrientation:interfaceOrientation];
}
else
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
}
In each of the view controllers for each of the tabs I have overridden the method and returned YES for each orientation I want to support. All well and good and everything works as it should. If I try and do a rotation on a tab that doesn’t support the rotation, nothing happens.
The problem occurs if I move from a tab thats rotated to a tab that isnt supposed to support that rotation. The new tab is displayed rotated too! Screenshots for all this are included here:
http://tunepal.wordpress.com/2010/04/20/rotation-woes/
Is there any way I can make it rotate back to portrait on tapping the tab?
I have tried the unsupported setOrientation trick, but firstly it doesnt work correctly and secondly I received a warning from Apple for including it in my last build.
If (as I suspect) there is no way to limit this behavior:
How do I make the microphone image scale when I rotate the device?
How do I make the buttons and the progress bar expand to fit the witdh of the toolbar?
Also, one of the tabs that rotates ok has a table, with a search bar. The first time I rotate to the right or to the left, I get a black bar to the right of the search bar. If I subsequently rotate back and rotate again, the bar disappears! I have enabled the struts and springs things on the search bar in the interface builder and it looks like it should behave correctly.
Any ideas about how to fix this?
Ideas, feedback much appreciated
Bryan
This isn't a full answer. Rotation is seriously inconsistent. You have done the right things. Several aspects don't work in the simulator, so you need to confirm all your testing on a device. Table headers and search bars don't resize to full width in older OS versions, so stick with 3.1.3 or higher.
Commonest problems:
implement the shouldAutorotateToInterfaceOrientation: to return YES;
if you use navigation controllers the root view controller must support the orientation;
if you have a toolbar the view controller for all items must support it;
and same for a tab bar controller.
You may need to turn on orientation notifications to get more useful information out of the device:
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(orientationChanged:)
name:UIDeviceOrientationDidChangeNotification object:nil];
Remember to turn it off and remove yourself from the notifications when you are done; this is supposed to have a high overhead.
Set the view contentMode property for your image to resize; together with autoresizingMask, which you are setting in IB, you should be OK.
Remember also that you can use two different nibs for portrait and landscape modes. There is an example project that sort of does this ("WhichWayIsUp"); see the View Controller Programming Guide also ("Creating an Alternate Landscape Interface").
If the rotation methods are being called, then the UI should be rotated consistently. You will find that they aren't always called when they should be.
It isn't hard to call a rotational transform on your views to force a rotation. It shouldn't be needed, but sometimes that's the only way they will rotate.
view.transform = CGAffineTransformMakeRotation(M_PI * n);
If you get it figured out, let us know.
It sounds like you are handling the rotation correctly while the tab is displayed. However, as you know, there's no quick way to switch rotations. What you will have to do is rotate the view yourself using CGAffineTransform. See this question: Is there a documented way to set the iPhone orientation?
To scale the image, you should be able to click the arrows inside the UIImageView housing the image in Interface Builder. There's a little arrow in the upper right hand corner you can click to see how the view behaves when it's rotated to make sure it scales correctly. But you'd probably be better off not scaling the image and hadling the rotation as in the answer to the linked question.

iPhone force rotation

I have been reading a ton on rotation, but not finding a solution to my query. Here goes:
I have a portrait application with a tabbar and hidden navigation controller in my tab. At a point in the app, the next view must be landscape.
The XIB layout has been done in landscape, so I want to bring up the xib without any translation or pixel moving code. (not thinking this is required) I have tried just pushing the view (remains in portrait), shifting the view using various methods (non seem to line thing up properly).
Is there a way to tell the view that it is already laid out for landscape prior to it being opened?
Thanks in advance!
Found it, this code does the trick in the viewdidload:
self.view.transform = CGAffineTransformIdentity;
self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(90));
self.view.bounds = CGRectMake(0.0, 0.0, 460.0, 320.0);
Still have 1 odd thing. No matter what I do to set the navigation bar to hidden, it does not rotate, and stays at the left side of the view.
[[self navigationController] setNavigationBarHidden:YES animated:NO];
Has anyone seed this behavior and solved?
I'm positive that you cannot 'force' a rotation. The system decides when to change the orientation of the device; so the 'orientation' properties are essentially read-only. I looked into this same problem a long time ago when I wanted to make sure a particular view always displayed in one orientation.
Due to this, most apps allow all of their views and view controllers to work in any of the orientations the app supports. I've found that trying to restrict the behavior of some views and view controllers ultimately creates more hassle, and can cause issues when transitioning between views and view controllers.
The code you posted will work for your view. You are not actually changing the orientation at all; your view is just behaving like it has been rotated by drawing in a rotated fashion. I'm not sure if you can do the same thing to the navigation bar or not, but it's worth a shot. If you are able to control the view properties of the navigation bar (it is a UIView as well), applying the same pattern you are using for your custom view should work.
Most apps that want a view to only be in landscape ultimately force their entire app to be in landscape. For instance, Flight Control only supports one orientation. Thus, the drawing code is pretty simple; regardless of orientation, just draw the view and rotate it to the one orientation it supports (either landscape left or right).
Your app's design wouldn't be that easy... it sounds like you are not designing a full-screen app. You would have to worry about the navigation bar and status bar being properly drawn.

iPhone autorotation only on specific screens in under a navigation controller

This is just an example of the basic problem I'm having, so don't worry if this situation sounds a bit pointless ;)
Let's say I have an app that's mainly a UINavigationController just two levels deep. The top level is a table with a list of image filenames, and the second level has just a UIImageView showing the image for the filename you tapped.
For an app such as this, does anyone know a good way to allow the table at the top level to autorotate while keeping the second level of images fixed in portrait mode?
So far I've been able to almost get there... but when I tap a filename while in landscape mode, the image slides into view in the wrong orientation even if the second level view controller's shouldAutorotateToInterfaceOrientation returns yes for only portrait modes.
There was no good way to do this in iPhone OS 2.x, but in 3.0, they've dramatically improved it.
In 2.x, the shouldAutorotateToInterfaceOrientation: delegate method was only obeyed for changes to the orientation, so you'd get the behavior you describe: if it was rotated in another view controller, it would stay rotated through pushes and pops even if the new view controller didn't support rotation to that orientation.
In 3.0, UINavigationController polls shouldAutorotateToInterfaceOrientation: on each push or pop and obeys what it returns the way you'd expect, e.g.: if you're currently rotated in Landscape Left orientation, and you push an instance of a view controller that only supports Portrait orientation via shouldAutorotateToInterfaceOrientation:, it automatically and instantly flips the logical orientation and slides in the new view the correct way in Portrait orientation.
Note that this will only work on applications linked against (and therefore requiring) 3.0. For applications linked against 2.x, it will emulate the old behavior.
The problem is that if you use auto rotation the entire UI (including the UIWindow instance I believe) is rotated.
Anything pushed onto the navigation controller at this point will be done in landscape.
So when you push the imageview, that is exactly what you get.
To get this to work, you have to either:
Handle the rotation of the root view
manually (using a transform)
Unrotate the image view by -PI/2
using a transform.
Either way you have to perform the transforms manually to get this to work.
As a side note, this may be bad UI design. As a user, I would expect as I drill down for images to appear rightside up. But this is without knowing the exact context of your app.