TheGeordie
TheGeordie

Reputation: 11

iPhone View Controller landscape / portrait rotation troubles

I'm trying to implement forced portrait / landscape orientation for different sub modes of my app. To do this I have a UINavigationController as the root controller and each sub mode has it's own view controller that are one of either

@interface iosPortraitViewController : UIViewController

or

@interface iosLandscapeViewController : UIViewController

with

-(BOOL)shouldAutorotate;
-(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation;
-(NSUInteger) supportedInterfaceOrientations;

overloaded and set correctly based on the orientation type for each of them. e.g. iosLandscapeViewController::supportedInterfaceOrientations returns UIInterfaceOrientationMaskLandscape.

When the sub mode in the app changes, the corresponding view controller is presented on the root view controller using present / dismissViewController and this forces the orientation to re-evaluate and call the functions in the overloaded view controller classes and orientate itself accordingly.

My problem is that when we switch to landscape, the frame of the sub mode view is offset from the top left corner of the screen which is where it should be (it's a full screen view showing a background pic).

For debugging purposes, if I change the view controller for that sub mode to a iosPortraitViewController the view information is:

size = 480.000000 320.000000
bounds = 0.000000 0.000000 480.000000 320.000000
frame = 0.000000 0.000000 480.000000 320.000000
centre = 240.000000 160.000000
user interaction enabled = 1
hidden = 0
transform = 1.000000 0.000000 0.000000 1.000000 : 0.000000 0.000000

When in landscape mode, which is what it needs to be, the view information is:

size = 480.000000 320.000000
bounds = 0.000000 0.000000 480.000000 320.000000
frame = 80.000000 -80.000000 320.000000 480.000000 
centre = 240.000000 160.000000
user interaction enabled = 1
hidden = 0
transform = 0.000000 -1.000000 1.000000 0.000000 : 0.000000 0.000000 

The 80, -80 origin of the frame is the problem I'm having - it should be 0,0. (if anyone could point out how it's getting 80,-80 too that would be appreciated - I can see it for X but not Y).

Also notice how the w and h in the frame are swapped around and the transform is a rotation transform - From reading, I'm guessing the UIWindow (which is always in portrait mode) has applied this to the view transform of the root view controller?

What can I do to get around this? I need the frame of the view controller view to be in the correct place (i.e origin at 0,0). I tried hardcoding it but it didn't appear to work and its not a very good solution anyway - I'm much rather understand what's going on and how to fix it properly.

Thanks!

:-)

Upvotes: 0

Views: 433

Answers (1)

dlp
dlp

Reputation: 581

To support an alternate landscape interface, you must do the following:

  1. Implement two view controller objects. One to present a portrait-only interface, and the other to present a landscape-only interface.
  2. Register for the UIDeviceOrientationDidChangeNotification notification. In your handler method, present or dismiss the alternate view controller based on the current device orientation.

From apple's guide to Creating an Alternate Landscape Interface

Also from the guide:

@implementation PortraitViewController
- (void)awakeFromNib
{
    isShowingLandscapeView = NO;
    [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                 selector:@selector(orientationChanged:)
                                 name:UIDeviceOrientationDidChangeNotification
                                 object:nil];
}

- (void)orientationChanged:(NSNotification *)notification
{
    UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
    if (UIDeviceOrientationIsLandscape(deviceOrientation) &&
        !isShowingLandscapeView)
    {
        [self performSegueWithIdentifier:@"DisplayAlternateView" sender:self];
        isShowingLandscapeView = YES;
    }
    else if (UIDeviceOrientationIsPortrait(deviceOrientation) &&
             isShowingLandscapeView)
    {
        [self dismissViewControllerAnimated:YES completion:nil];
        isShowingLandscapeView = NO;
    }
}

Upvotes: 1

Related Questions