Switching between Portrait and Landscape Views

Discussion in 'iOS Programming' started by daproject, May 29, 2013.

  1. daproject macrumors newbie

    Joined:
    May 29, 2013
    #1
    Hi Forum,

    I have a question regarding an example which I saw about swaping between views (landscape and portrait). Basically explicitly defining where various UI objects should be in each view. Now I know how to make it work correctly from the example, but I really want to understand HOW it works. Any help is greatly appreciate.

    Figure 1: how I have laid out my nib
    [​IMG]

    ViewController.h file
    Code:
    #import <UIKit/UIKit.h>
    
    @interface BIDViewController : UIViewController
    
    @property (strong, nonatomic) IBOutlet UIView *portrait;
    @property (strong, nonatomic) IBOutlet UIView *landscape;
    @property (strong, nonatomic) IBOutletCollection(UIButton) NSArray *foos;
    @property (strong, nonatomic) IBOutletCollection(UIButton) NSArray *bars;
    
    - (IBAction)buttonTapped:(UIButton *)sender;
    
    @end
    With the following method in Viewcontroller.m

    Code:
    -(void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
    {
        if (toInterfaceOrientation == UIInterfaceOrientationPortrait) {
            self.view = self.portrait;
        } else if (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft) {
            self.view = self.landscape;
        }
    }
    here is what the output looks like; When the app starts out , its correct exactly how it looks in the nib portrait view, but when you rotate it it looks like the second pic.
    [​IMG] [​IMG]

    Question 1:
    Since I have laid out the Landscape view in the nib file; how come it does not look like that when I rotate the device??


    if i change rotate method to the following

    Code:
    if (toInterfaceOrientation == UIInterfaceOrientationPortrait) {
            self.view = self.portrait;
            self.view.transform = CGAffineTransformIdentity;
            self.view.transform = CGAffineTransformMakeRotation(degreesToRadians(0));
            self.view.bounds = CGRectMake(0.0, 0.0, 320., 548);
        } else if (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft) {
            self.view = self.landscape;
            self.view.transform = CGAffineTransformIdentity;
            self.view.transform = CGAffineTransformMakeRotation(degreesToRadians(-90));
            self.view.bounds = CGRectMake(0.0, 0.0, 568, 300.0);
            CGRect landscape_frame = self.view.frame;
            CGRect landscape_bound = self.view.bounds;
    }
    THen it will work :):):)
    [​IMG]

    Question 2:
    Why do we have to set the value of self.view.transform to CGAffineTransformIdentity? Why cant we just call self.view.transform = CGAffineTransformMakeRotation(degreesToRadians(-90));?


    Question 3:
    Why do we need to set the bounds? Again we specified this view in the nib


    Question 4:
    For debug purposes I created to CGRects as you can see and looked at their output. The bound value is just as I put them to be in my code, but the CGRect for Landscame_frame which is the origin and dimensions of the landscape view with respect to its super view is landscape_frame = origin=(x=20, y=0) size=(width=300, height=568. Where is the (0,0) point of a device in landscape mode? I dont get the (x=20,y=0).


    Question 5:
    Why is the frame size (width=300, height=568) ??? Hows the width of the fram 300???


    landscape_frame = origin=(x=20, y=0) size=(width=300, height=568)
    landscape_bound = origin=(x=0, y=0) size=(width=568, height=300)
     
  2. Duncan C, May 31, 2013
    Last edited by a moderator: May 31, 2013

    Duncan C macrumors 6502a

    Duncan C

    Joined:
    Jan 21, 2008
    Location:
    Northern Virginia
    #2
    I've written quite a few iOS apps, and I have always been able to avoid swapping view hierarchies when rotating views.

    I would advise you to find another way to handle rotation if at all possible. Having a second view hierarchy for portrait and landscape seems fraught with problems and downsides, and no major upside that I can see.

    A number of the "cons" of doing it that way:

    1. You have to lay out your interface twice, including all the outlet and action links
    2. You have to test everything twice.
    3. Anytime you change anything you have to change it twice. Add in iPhone and iPad, and now you've got 4 different view layouts to maintain. Ugh.
    4. Device rotation does not animate like users expect. Instead it JUMPS from one layout to the next.
     
  3. daproject thread starter macrumors newbie

    Joined:
    May 29, 2013
    #3

    thanks alot for your advice
     
  4. Duncan C macrumors 6502a

    Duncan C

    Joined:
    Jan 21, 2008
    Location:
    Northern Virginia
    #4
    You're welcome.
     
  5. PhoneyDeveloper macrumors 68030

    PhoneyDeveloper

    Joined:
    Sep 2, 2008
    #5
    I think the problem with your example is that there's no container view controller, like a navigation controller or tab bar controller. Are your views added directly to the window object or to a view that's added to the window object.

    The window's frame and bounds don't change, regardless of the orientation. The navigation controller knows about this and it applies the transforms and resetting of frame etc. that is needed when the orientation changes.

    "Normal" apps don't have to deal with this problem because they always have a container view controller. Typically only game authors think it's better to do these things manually.
     
  6. daproject thread starter macrumors newbie

    Joined:
    May 29, 2013
    #6
    when selecting a "view" file from the interfacebuilder when creating a new XIB file it comes with a view object and thats visible on the IB dock.
     
  7. Duncan C macrumors 6502a

    Duncan C

    Joined:
    Jan 21, 2008
    Location:
    Northern Virginia
    #7
    No, you don't need a container view controller in order to handle auto-rotation. If you create a single view project and set it up to handle all orientations it works just fine.
     

Share This Page