8

I have a UIView as a XIB in Portrait mode.

This view is added programmatically to the viewcontroller like this:

NSArray *nibObjects = [[NSBundle mainBundle] loadNibNamed:@"InputView" owner:self options:nil];
    InputView *inputView = (InputView*)[nibObjects objectAtIndex:0];
    [self.view addSubview:inputView];

This view has autoresizing masks set up properly and rotates fine when the orientation changes from Portrait to landscape.

However, if the orientation is already landscape and I create the view after the orientation change, it has its initial portrait orientation.

Is there a way to tell the view to initialize or resize itself to portrait by using its masks?

Thanks in advance for any reply!

EDIT: Using the suggestions of occulus and Inder Kumar Rathore (thanks guys!), I altered the code to this:

InputView *inputView = (InputView*)[nibObjects objectAtIndex:0];
[self.view addSubview:inputView];
[self.view setNeedsLayout];
[self.view layoutSubviews];
[self.view layoutIfNeeded];
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
[self shouldAutorotateToInterfaceOrientation:orientation];

Unfortunately, there is no change at all. I think I found someone asking the same question:

When adding a sub view the view does not resize if the app is in landscape mode

The answer identifies the problem correctly, but is not very encouraging... Sure, I could create two nibs or resize the frame, but this seems so contrary to the idea of auto-resizing. I find it hard to believe that there is no way to tell a nib after awakening and adding it to a view to use its autoresize features...something that works flawless when the device rotates.

EDIT 2:

The solution of idz works:

InputView *inputView = (InputView*)[nibObjects objectAtIndex:0];
[self.view addSubview:inputView];
inputView.frame = self.view.bounds;
[inputView show];

Thanks!

Community
  • 1
  • 1
marimba
  • 3,116
  • 5
  • 26
  • 29
  • I had this problem, with two wrinkles: (1) I was using a controlled view, the nib loaded a UIVC; & (2) it only showed up under iOS 4.3, not 5.0. yasirmturk's method fixed it for me. – Clay Bridges Jan 05 '12 at 11:41

4 Answers4

19

Often a NIB/XIB file contains a UIViewController that takes care of all of this. In this case, since their is no view controller (in the NIB/XIB) you need to take over its post-load duties.

Calling layoutSubviews directly, or indirectly via setNeedsLayout or layoutIfNeeded won't do you much good because the default implementation does nothing.

Assuming you want input view to fill the bounds of self.view you do the following:

InputView *inputView = (InputView*)[nibObjects objectAtIndex:0];
[self.view addSubview:inputView];
inputView.frame = self.view.bounds;
[inputView show];

All the resize masks of the sub-views must be correctly set for this to work and, obviously, if you don't want to fill the full bounds you may want to adjust the frame.

idz
  • 12,825
  • 1
  • 29
  • 40
  • That works! Thanks a lot! Will edit the post to reflect your solution. – marimba May 14 '11 at 08:48
  • If you wanted you could be really fancy and check the autoresize masks and only just one dimension, but it seems to me that most of the time, in these situations you want both to adjust. I'll post a link to this in the other question. Glad it worked for you! – idz May 14 '11 at 08:50
  • I designed the input view to be reusable, what I am going to do is to alter show: to showOnViewController:(UIViewController*)vc, that way the InputView can set it's own frame. – marimba May 14 '11 at 08:55
  • You could do that, but then if you ever wanted it to only be part of a more complex view you would have to change your code. That's why the UIKit UIView subclasses don't set their own frames. The view controller is the class that knows about all thats going on the screen it manages. It's a good idea to let it be in control. Just a thought. – idz May 14 '11 at 08:58
  • I have a view-controlled view with this exact problem. yasirmturk's answer is the one that worked for me. – Clay Bridges Jan 05 '12 at 11:37
1
[self.view addSubview:viewSpinner];
viewSpinner.frame = self.view.frame;
[viewSpinner setNeedsLayout];

This works for me (Y)

yasirmturk
  • 1,924
  • 2
  • 22
  • 32
1

I don't know if you still have this issue.

Let's say you have the following architecture:

  • window
    • subviewcontroller

(you implemented shouldautorotate correct to answering the wanted orientations)

Into this subviewcontroller you want to add the views of new UIViewControllers by just calling the addSubview function.

Instead of implementing the bounds manipulation in shouldautorotate, you should implement it in

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation{
  self.newUIViewController.view.frame = self.view.bounds;
}

didRotateFromInterface... is called after shouldRotate. In this function the bounds are already setup correctly.

This way you don't need so much manipulation by code.

FishBasketGordo
  • 22,904
  • 4
  • 58
  • 91
Phil K.
  • 116
  • 1
  • 2
0

See this related question:

When do autoresizing masks take effect in iOS?

So after loading your new view from the nib, and adding as a subview to self.view, try calling setNeedsLayout.

Community
  • 1
  • 1
occulus
  • 16,959
  • 6
  • 53
  • 76