Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Loaded UIView from NIB - Wrong Frame Size

Tags:

ios

Ok, so I've created a UIView in interface builder. I'm using AutoLayout and I've got one subview of this view pinned to all four sides.

Here's what I don't understand. When I load this NIB file using loadNibNamed. I then get a reference to the view. I set the frame for this view. And yet, when I access the subview (using [containerView viewWithTag:1]) it's frame hasn't been automatically resized. What gives? If you change the frame for a parent view, why wouldn't the subview frame change as well?

It doesn't make any sense.

Why can't you just load a UIView, set it's frame and have all the subviews adjust as appropriate (ESPECIALLY since I'm using AutoLayout!)?

EDIT: To be clear, all I want to do is be able to define a UIView hierarchy in IB with appropriate AutoLayout constraints and then be able to load and display that view on the screen sometimes at different sizes? Why is this so hard?

like image 990
Neil Sainsbury Avatar asked Sep 20 '13 05:09

Neil Sainsbury


2 Answers

UIKit doesn't update subview geometry immediately when you change a view's geometry. It batches up the updates for efficiency.

After running your event handler, UIKit checks whether any views in the on-screen window hierarchy need to be laid out. If it finds any, it lays them out by solving your layout constraints (if you have any) and then sending layoutSubviews.

If you want to solve the constraints and lay out a view's subviews immediately, simply send layoutIfNeeded to the view:

someView.frame = CGRectMake(0, 0, 200, 300);
[someView layoutIfNeeded];
// The frames of someView.subviews are now up-to-date.
like image 160
rob mayoff Avatar answered Nov 19 '22 23:11

rob mayoff


I too had the same problem, I was creating a tutorial view where in which I wanted to add multiple UIViews to a scrollview. While I was trying to get the frame from xib, it gave always 320 and because of that the offset for the pages were wrong and my views looked crappy in iPhone6 and 6plus.

I then used pure autolayout approach, ie instead of using the frame, I added constraints through VFL so that subviews fit exactly to the superview. Below is the snapshot of code where I create around 20 UIViews from Xib and add properly to scrollview

Full code here ScrollViewAutolayout

 Method to layout the childviews in the scrollview.
 @param nil
 @result layout the child views
 */
-(void)layoutViews
{
    NSMutableString *horizontalString = [NSMutableString string];
    // Keep the start of the horizontal constraint
    [horizontalString appendString:@"H:|"];
    for (int i=0; i<viewsArray.count; i++) {
        // Here I am providing the index of the array as the view name key in the dictionary
        [viewsDict setObject:viewsArray[i] forKey:[NSString stringWithFormat:@"v%d",i]];
        // Since we are having only one view vertically, then we need to add the constraint now itself. Since we need to have fullscreen, we are giving height equal to the superview.
        NSString *verticalString = [NSString stringWithFormat:@"V:|[%@(==parent)]|", [NSString stringWithFormat:@"v%d",i]];
        // add the constraint
        [contentScrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:verticalString options:0 metrics:nil views:viewsDict]];
        // Since we need to horizontally arrange, we construct a string, with all the views in array looped and here also we have fullwidth of superview.
        [horizontalString appendString:[NSString stringWithFormat:@"[%@(==parent)]", [NSString stringWithFormat:@"v%d",i]]];
    }
    // Close the string with the parent
    [horizontalString appendString:@"|"];
    // apply the constraint
    [contentScrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:horizontalString options:0 metrics:nil views:viewsDict]];
}
like image 23
anoop4real Avatar answered Nov 20 '22 01:11

anoop4real