views:

748

answers:

2

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 theshouldAutorotateToInterfaceOrientation:

  • (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

A: 

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: http://stackoverflow.com/questions/181780/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.

Don
If you have autorotate correctly enabled, the views should be rotated for you. In practice it doesn't work that way, but it should.
Paul Lynch
Yes, but I think his problem is that he wants to rotate back to portrait if it is in landscape when one of the tab bar buttons is tapped.
Don
And, your `view.transform = CGAffineTransformMakeRotation(M_PI * n); ` solution below provides that.
Don
A: 

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:

  1. implement the shouldAutorotateToInterfaceOrientation: to return YES;
  2. if you use navigation controllers the root view controller must support the orientation;
  3. if you have a toolbar the view controller for all items must support it;
  4. 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.

Paul Lynch
Well I kind of got it working ok by disabling the unwanted auto rotations for certain tabs using shouldAutorotateToInterfaceOrientationIt will still display a rotated tab if you switch to it from another tab as the Tab Manager doesn't honor shouldAutorotateToInterfaceOrientation. Its a pain in the ass. I figured out how to scale the images by changing the view mode to Aspect Fit in Interface Builder, so the views look okish. It seems the only way to get the buttons to expand is to create a separate nib (unless anyone has any other ideas).
skooter500