Search code examples
iphoneiosuivieworientationdevice-orientation

Programatic UIViews being rotated correctly


I have been doing pretty much all of my User Interface programmatically with slight alterations being performed in Interface Builder.. but 99% of all the UI is exclusively done in code, because I feel there is a certain amount of flexibility gained by doing it this way.

However I am now having issues dealing with the rotation of the device, as I have several UIViews being added as subviews I am faced with a rotational problem as this is how I declare the views generally

htmlTest.webViewTest.frame = CGRectMake(4.0, 4.0, 312.0, 363.0);

and because of this fixed CGRectMake when the device is rotated the view stays the same size and dosent fit the orientation of the view properly.

So I have worked on a solution which is in my opinion horrible.. There are a couple of views that I animate in and users can select options from them then I animate them out.. but they need to be able to handle loading in either portrait or landscape and then if while they are loaded they need to be able to handle a rotation from either orientation to the other.

This is how I have done one of the views.

#pragma createAwesomeJumpBar
- (void)jumpBarButtonPosition:(int)changeView
{
    // ChangeView is used to check if the this method is being called from a device rotation or from a button press (0, being rotation and 1, being tabbarButton touch

    // if tabbar selected
    if (changeView == 1) {
        if  ([[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationPortrait)
        {
            if (![jumpBarContainerPortrait superview]) {
                // load portrait view
                jumpBarContainerPortrait = [[UIView alloc] initWithFrame:CGRectMake(0.0, 480.0, 320, (jumpBarHeightPortrait + 49.0))];
                jumpBarContainerPortrait.backgroundColor = [UIColor scrollViewTexturedBackgroundColor];

                // add jumpbar container to view
                [self.view insertSubview:jumpBarContainerPortrait belowSubview:actionTabBar];

                [UIView animateWithDuration:0.6
                                      delay:0.0f
                                    options:UIViewAnimationCurveEaseIn 
                                 animations:^{

                                     jumpBarContainerPortrait.frame = CGRectMake(0.0, (367 - jumpBarHeightPortrait), 320.0, (jumpBarHeightPortrait + 49.0)); // display jumpBar


                                 } completion:^(BOOL finished) {
                                     if (finished) {
                                         NSLog(@"YAY!");
                                     }
                                 }];
            }
            else if ([jumpBarContainerPortrait superview]) {
                //unload portrait view
                [UIView animateWithDuration:0.6
                                      delay:0.0f
                                    options:UIViewAnimationCurveEaseIn 
                                 animations:^{

                                     jumpBarContainerPortrait.frame = CGRectMake(0.0, 480.0, 320.0, (jumpBarHeightPortrait + 49.0)); // display jumpBar

                                     // remove selected tabButton highlight
                                     [actionTabBar setSelectedItem:nil];


                                 } completion:^(BOOL finished) {
                                     if (finished) {

                                         // remove subView for superView
                                         [jumpBarContainerPortrait removeFromSuperview];

                                     }
                                 }];

            }

        }
        else if ([[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationLandscapeLeft || [[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationLandscapeRight)
        {
            if (![jumpBarContainerLandscape superview]) {
                // load landscape view
                jumpBarContainerLandscape = [[UIView alloc] initWithFrame:CGRectMake(0.0, 320, 480.0, (jumpBarHeightLandscape + 49.0))];
                jumpBarContainerLandscape.backgroundColor = [UIColor scrollViewTexturedBackgroundColor];

                // add jumpbar container to view
                [self.view insertSubview:jumpBarContainerLandscape belowSubview:actionTabBar];

                [UIView animateWithDuration:0.6
                                      delay:0.0f
                                    options:UIViewAnimationCurveEaseIn 
                                 animations:^{

                                     jumpBarContainerLandscape.frame = CGRectMake(0.0, (207 - jumpBarHeightLandscape), 480.0,  (jumpBarHeightLandscape + 49.0)); // display jumpBar


                                 } completion:^(BOOL finished) {
                                     if (finished) {
                                         NSLog(@"YAY!");
                                     }
                                 }];
            }
            else if ([jumpBarContainerLandscape superview]) {
                // remove landscape view
                [UIView animateWithDuration:0.6
                                      delay:0.0f
                                    options:UIViewAnimationCurveEaseIn 
                                 animations:^{

                                     jumpBarContainerLandscape.frame = CGRectMake(0.0, 320, 480.0, (jumpBarHeightLandscape + 49.0)); // display jumpBar

                                     [actionTabBar setSelectedItem:nil];

                                 } completion:^(BOOL finished) {
                                     if (finished) {

                                         // remove subView for superView
                                         [jumpBarContainerLandscape removeFromSuperview];
                                     }
                                 }];
            }

        }
    }
    // if device rotated selected
    else if (changeView == 0) {
        if  ([[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationPortrait)
        {
            if([jumpBarContainerLandscape superview])
            {
            // Device is changing from landscape to protrait change views to fit
            // load landscape view
            jumpBarContainerPortrait = [[UIView alloc] initWithFrame:CGRectMake(0.0, (367 - jumpBarHeightPortrait), 320.0, (jumpBarHeightPortrait + 49.0))];
            jumpBarContainerPortrait.backgroundColor = [UIColor scrollViewTexturedBackgroundColor];
            jumpBarContainerPortrait.alpha = 1.0;

            // add jumpbar container to view

                [UIView transitionFromView:jumpBarContainerLandscape
                                    toView:jumpBarContainerPortrait
                                  duration:animationSpeed
                                   options:UIViewAnimationOptionTransitionCrossDissolve 
                                completion:NULL];

                [self.view insertSubview:jumpBarContainerPortrait belowSubview:actionTabBar];


            }
        }
        else if ([[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationLandscapeLeft || [[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationLandscapeRight)
        {
            if ([jumpBarContainerPortrait superview])
            {
            // Device is changing from portrait to landscape change views to fit
            // load landscape view
            jumpBarContainerLandscape = [[UIView alloc] initWithFrame:CGRectMake(0.0, (207 - jumpBarHeightLandscape), 480.0,  (jumpBarHeightLandscape + 49.0))];
            jumpBarContainerLandscape.backgroundColor = [UIColor scrollViewTexturedBackgroundColor];
            jumpBarContainerLandscape.alpha = 1.0;

            // add jumpbar container to view

                [UIView transitionFromView:jumpBarContainerPortrait
                                    toView:jumpBarContainerLandscape
                                  duration:animationSpeed
                                   options:UIViewAnimationOptionTransitionCrossDissolve
                                completion:NULL];

                [self.view insertSubview:jumpBarContainerLandscape belowSubview:actionTabBar];



            }

        }
    }
}

in this example, I have two views landscape and portrait, obviously as the names go each are for their respective orientations.. the logic above goes along the lines of this

if tabbarselected 

if !view visible
if device orientation portrait 
animate in portrait view.
if device orientation landscape
animate in landscape view

if view visible
if device orientation portrait
animate out portrait view
clear tabbar
if device orientation landscape
animate out landscape view
clear tabbar

if !tabbarselected //meaning listener has identified orientation of device has changed 

if device orientation portrait
unload portrait 
load landscape

if device orientation landscape
unload landscape
load portrait

I would like to know if there is an easier way than going through all of this hassle! I am still fairly inexperienced so this was my best attempt.. I am hoping someone out there knows of an easier approach than having to do all of this leg work to get views being added to other views as subviews adjusting for orientation properly

any help would be greatly appreciated! I'm desperate lol :)


Solution

  • See the autoresizingMask documentation. Gives you all the same springs and struts control that you have in Interface Builder. E.g.:

    CGRect frame = CGRectMake(margin, margin, self.view.frame.size.width - margin * 2, self.view.frame.size.height - margin * 2);
    UIView *mySubview = [[UIView alloc] initWithFrame:frame];
    [self.view mySubview];
    mySubview.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    

    Also, if you decide that autoresizingMask is not enough (for example, when you're moving objects with respect to each other to really fine tune the portrait versus landscape orientation), I'd suggest you do this layout process in viewWillLayoutSubviews for iOS5, (or willAnimateRotationToInterfaceOrientation in iOS4 or earlier). This way you don't need to animate the change yourself and the animation will be done in conjunction with the rest of the screen rotation animation.