Question

I have a VC where the user either takes a photo or selects one from their library.

Once the photo is taken/selected it is passed to a UIImageView on the next VC.

I would like to show this View Controller, ONLY in the Orientation that the image is in. So if the user takes a photo in landscape left (once they select Use), the next view controller should load in Landscape left with that image in the UIImageView. If they take the image in portrait the view controller loads in portrait. Once the VC is loaded in the correct orientation, it should not move (rotate any more).

This is what I have tried so far, but cannot get it to work how I expect:

#pragma mark -
#pragma mark - Auto Rotation Overrides
- (BOOL)shouldAutorotate {
    if (self.photoImage != NULL) {
        // Check that photoImage has an image
        if (self.photoImage.imageOrientation == 1 || self.photoImage.imageOrientation == 0) {
            // Landscape left = 0, Landscape rigt = 1
            return YES;
        } else {
            // Portrait normal = 3, portait upside down = 2
            return NO;
        }
    }

    // Fallback to portrait
    return NO;
}

-(NSUInteger)supportedInterfaceOrientations {
    if (self.photoImage != NULL) {
        // Check that photoImage has an image
        if (self.photoImage.imageOrientation == 0) {
            return UIInterfaceOrientationMaskLandscapeLeft;
        } else if (self.photoImage.imageOrientation == 1) {
            return UIInterfaceOrientationMaskLandscapeRight;
        } else {
            return UIInterfaceOrientationMaskPortrait;
        }
    }

    // Fallback to Portrait
    return UIInterfaceOrientationMaskPortrait;
}


- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    if (self.photoImage != NULL) {
        // Check that photoImage has an image
        if (self.photoImage.imageOrientation == 0) {
            return UIInterfaceOrientationLandscapeLeft;
        } else if (self.photoImage.imageOrientation == 1) {
            return UIInterfaceOrientationLandscapeRight;
        } else {
            return UIInterfaceOrientationPortrait;
        }
    }

    // Fallback to Portrait
    return UIInterfaceOrientationPortrait;
}

-----EDIT-----

As shouldAutoRotate is not called until the device is actually rotated, how do I get it to automatically on viewDidLoad change the orientation based on the image orientation. I see the supportInterfaceOrientations method is called and only a Landscape is returned, but doesn't move the view straight away...?

-----EDIT2-----

Does preferredInterfaceOrientationForPresentation work in IOS6 too? I can setup my Navigation Controller subclass to look at self.topViewControllers preferredInterfaceOrientationForPresentation, however this seems to mean that every single topViewController needs to have this method. Ideally I want to setup the subclass to say: if the topViewController has a response to preferredInterfaceOrientationForPresentation, then use that else portrait/default. Can this be done?

If so, surely I can update the preferredInterfaceOrientationForPresentation which would load that VC in the correct orientation then shouldAutoRotate would control it not being rotated back to another orientation?

Was it helpful?

Solution

From what I understand, there is no way to force a rotation event, so you have to come with some tricksy stuff. I did a google search for "force a uiview to rotate" and found some links that may help:

Removing and re-adding the view from the window

Rotating the view with a transform

Personally, I would try the transform first, here is the relevant code:

[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:YES];
self.view.transform = CGAffineTransformIdentity;
self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(90));
self.view.bounds = CGRectMake(0.0, 0.0, 460.0, 320.0);

I am not sure if setting the status bar orientation will change the orientation of the nav bar, if you are using one...

OTHER TIPS

What I've done in the past for situations like this is to create separate viewControllers for landscape and portrait (for instances I don't want the view to auto-rotate). Once you have your separate view controllers, you can just look at the dimensions of the UIImage like so:

    if(sourceImage.size.width>sourceImage.size.height)
    {
       LandscapeViewController *LandscapeView = [[LandscapeViewController] init];
        [self presentViewController:LandscapeView animated:YES completion:nil];
        NSLog(@"go to Landscape View");
    }
    //Else load into portrait Edit view
    else
    {
        PortraitViewController *PortraitView = [[PortraitViewController alloc] init];
        [self presentViewController:PortraitView animated:YES completion:nil];
        NSLog(@"go to Portrait View");
    }

I'm sure there are more efficient ways, but this is incredibly simple and works!

Since iOS 6, it is the navigationController which handles the orientation. As you thought, you can subclass it and check if the topviewcontroller has the selector needed using respondsToSelector: .

- (NSUInteger)supportedInterfaceOrientations {
        if([self.topViewController respondsToSelector:@selector(supportedInterfaceOrientations)]){
            return [self.topViewController supportedInterfaceOrientations];
        }
    return [super supportedInterfaceOrientations];
}

My need was to force the landscape. I also added in the controller's viewDidLoad :

[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:NO];

You need to change the orientation to the one you want.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top