Rotate UIViewController to counteract changes in UIInterfaceOrientation
Asked Answered
E

2

1

I've been searching a lot on this, and can't find anything to help me.

I have a UIViewController contained within another UIViewController. When the parent UIViewController rotates, say from Portrait to LandscapeLeft, I want to make it look as though the child didn't rotate. That is to say. I want the child to have the same orientation to the sky regardless of the parent's orientation. If it has a UIButton that's upright in Portrait, I want the right-side of the button to be "up" in UIInterfaceOrientationLandscapeLeft.

Is this possible? Currently, I'm doing really gross stuff like this:

-(void) rotate:(UIInterfaceOrientation)fromOrientation: toOr:(UIInterfaceOrientation)toOrientation
{
    if(((fromOrientation == UIInterfaceOrientationPortrait) && (toOrientation == UIInterfaceOrientationLandscapeRight))
       || ((fromOrientation == UIInterfaceOrientationPortraitUpsideDown) && (toOrientation == UIInterfaceOrientationLandscapeLeft)))
    {

    }
    if(((fromOrientation == UIInterfaceOrientationLandscapeRight) && (toOrientation == UIInterfaceOrientationPortraitUpsideDown))
       || ((fromOrientation == UIInterfaceOrientationLandscapeLeft) && (toOrientation == UIInterfaceOrientationPortrait)))
    {

    }
    if(((fromOrientation == UIInterfaceOrientationPortrait) && (toOrientation == UIInterfaceOrientationLandscapeLeft))
       || ((fromOrientation == UIInterfaceOrientationPortraitUpsideDown) && (toOrientation == UIInterfaceOrientationLandscapeRight)))
    {

    }
    if(((fromOrientation == UIInterfaceOrientationLandscapeLeft) && (toOrientation == UIInterfaceOrientationPortraitUpsideDown))
       || ((fromOrientation == UIInterfaceOrientationLandscapeRight) && (toOrientation == UIInterfaceOrientationPortrait)))
    {

    }
    if(((fromOrientation == UIInterfaceOrientationPortrait) && (toOrientation == UIInterfaceOrientationPortraitUpsideDown))
       || ((fromOrientation == UIInterfaceOrientationPortraitUpsideDown) && (toOrientation == UIInterfaceOrientationPortrait)))
    {

    }
    if(((fromOrientation == UIInterfaceOrientationLandscapeLeft) && (toOrientation == UIInterfaceOrientationLandscapeRight))
       || ((fromOrientation == UIInterfaceOrientationLandscapeRight) && (toOrientation == UIInterfaceOrientationLandscapeLeft)))
    {

    }   
}

which seems like a perfectly good waste of code. Furthermore, I was planning on using CGAffineTransform (like cited here: http://www.crystalminds.nl/?p=1102) but I'm confused about whether I should change the view's dimensions to match what they will be after the rotation.

The big nightmare here is that you have to keep track of a global "orientation" variable. If you don't, the illusion is lost and the ViewController is rotated into whatever.

I could really use some help on this, thanks!

Emma answered 22/3, 2010 at 3:14 Comment(0)
D
5

The best thing you can do is to change the frames of ur subview frames according to ur interface orientations. You can do it like:

 #pragma mark -
 #pragma mark InterfaceOrientationMethods

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    return (interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown || interfaceOrientation == UIInterfaceOrientationLandscapeRight || interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}

//--------------------------------------------------------------------------------------------------------------------------------------------------------------------

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
    [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
    if(toInterfaceOrientation == UIInterfaceOrientationPortrait || toInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown){
        //self.view = portraitView;
        [self changeTheViewToPortrait:YES andDuration:duration];

    }
    else if(toInterfaceOrientation == UIInterfaceOrientationLandscapeRight || toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft){
        //self.view = landscapeView;
        [self changeTheViewToPortrait:NO andDuration:duration];
    }
}

//--------------------------------------------------------------------------------------------------------------------------------------------------------------------

- (void) changeTheViewToPortrait:(BOOL)portrait andDuration:(NSTimeInterval)duration{

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:duration];

    if(portrait){
        //change the view and subview frames for the portrait view
    }
    else{   
        //change the view and subview  frames for the landscape view
    }

    [UIView commitAnimations];
}

Hope this helps.

Dorian answered 22/3, 2010 at 8:12 Comment(3)
Thanks Madhup. When you advise the "change the view and subview frames for the portrait view" - is this where I'd do a CGAffineTransform? Or should I have some sort of separate way to rotate the UIView/UIViewController? I need all elements to behave the same way, just have a different orientation. Also, what did you mean by the commented-out self.view = portraitView ? I would use these methods from the get-go, but I don't know how to have a sideways UITableView or a sideways UIButton or anything like that. Thanks again!Emma
@Peter Hajas: I don't perform CGAffine transforms rather I get the frame positions from the xib for portrait and landscape view and change the frame of my subviews accordingly.Dorian
I'm trying to implement this methods, but whenever I rotate the simulator device none of the methods get fired. Would you know why?Pasha
A
0

i realised something.. let's say our project have multiple layer of ViewController (as in if you add subview of other view controller to your view controller)

willRotateToInterfaceOrientation:duration method will not be called for the 2nd layer of ViewController...

so what i did was, after i initialise my 2nd layer view controller from my top most layer, then when willRotateToInterfaceOrientation:duration method is called on the top-most layer, i will call willRotateToInterfaceOrientation:duration for 2nd layer view controller as well

Album answered 25/8, 2010 at 3:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.