Tom Fobear
Tom Fobear

Reputation: 6749

UIView loaded with Nib autoresizing issue

I have a UIView subclass -

@interface DatePickerPopup : UIView
    UIToolbar *toolbar;
    UIDatePicker *datePicker;
@end

@implementation

- (id)initWithFrame:(CGRect)frame
{
    NSArray *xib = 
        [[NSBundle mainBundle] 
            loadNibNamed:@"DatePickerPopup" 
                  owner:self 
                options:nil];
    self = [xib objectAtIndex:0];
    if (self) {

    }
    return self;
}
@end

and the nib looks like -
nib ib autoresizing

In my UIViewController containing the DatePickerPopup (datePopup):

- (void)viewDidLoad
{
    datePopup = [[DatePickerPopup alloc] initWithRect:CGRectZero];
    CGRect newFrame = datePopup.frame;
    newFrame.y = 200.0f; //lets say this aligns it to the bottom in portrait
    datePopup.frame = newFrame;

    // Normally happens when accessory button pressed but for brevity...
    [self.view.superview addSubview:datePopup];
}

- (void)willAnimateRotationToInterfaceOrientation:
    (UIInterfaceOrientation)toInterfaceOrientation 
    duration:(NSTimeInterval)duration
{
    CGRect screen = [[UIScreen mainScreen] bounds];
    if (toInterfaceOrientation == UIInterfaceOrientationPortrait || 
        toInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)
    {
        self.datePopup.frame = 
            CGRectMake(0.0f, newHeightPortrait, screen.size.width, 260.0f);
    }
    else
    {
        self.datePopup.frame = 
            CGRectMake(0.0f, newHeightLandscape, screen.size.width, 260.0f);
    }
}

However, this gets stretched out for some reason when the orientation changes the view gets stretched to the height of the screen bounds - the navigation bar...

after viewDidLoad
after viewDidLoad

after willAutorotate...
after willAutorotate...

Upvotes: 4

Views: 1299

Answers (2)

cduhn
cduhn

Reputation: 17918

Since your view controller appears to be managed by a navigation controller, calling [self.view.superview addSubview:datePopup]; adds your popup as a subview of a UIViewControllerWrapperView, which is one of the private classes UIKit uses to implement the functionality of UINavigationController. Messing with UIKit's private view hierarchy is always risky. In this case, based on the behavior you're seeing, it seems likely that UIKit expects any subview of UIViewControllerWrapperView to be a view controller's view, so it resizes your popup accordingly.

I think the safest way to resolve this is to have your view controller's view be a wrapper that contains your tableView and, when necessary, your popup view. Unfortunately using a wrapper view means that the view controller can't be a UITableViewController. You'll have to change the superclass to UIViewController, set a custom tableView property, and manually adopt the UITableViewDataSource and UITableViewDelegate protocols.

Note: You might be tempted to add your popover as a subview of your window, but I'm not recommending that because UIWindow only autorotates its topmost subview corresponding to a view controller. This means that if you add your popover to your window, it won't autorotate.


EDIT: BTW, by reassigning self = [xib objectAtIndex:0]; in initWithFrame:, you're leaking the object that was originally alloc'd. If you're going to reassign self in this way, you should release the existing object first.

Upvotes: 2

tipycalFlow
tipycalFlow

Reputation: 7644

Add the

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 

method in the viewController class and return YES. If this method returns YES, only then will the device support landscape orientation. Try out this extra code and see if it helps... You can set the frame size for landscape in this method itself instead of the current method. PS: I just saw you've used a UIView instead of controller...you might want to change to controller.

Upvotes: 0

Related Questions