Search code examples
iosobjective-ccocoa-touchnslayoutconstraintvisual-format-language

Second view's size is ignored when constraining two views to fill the screen with visual format


I'm trying to set a constraint where the width of two views should fill the screen. If I change the width of one view, the other view should change accordingly:

[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-8-[view1]-8-[view2]-8-|" options:0 metrics:nil views:views]];

I think this is rather simple, but the code seems to ignore the size of view2. view1 keeps getting the entire width of the screen and setting the frame of view2 doesn't affect the width of view1.

What am I missing?


Solution

  • Assign a minimum size constraint to view2 as well, or "0 width" will be a valid solution to the constraints.

    [NSLayoutConstraint activateConstraints:
        [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-8-[view1(>=minSize)]-8-[view2(>=minSize)]-8-|" 
                                                options:0 
                                                metrics:@{@"minSize" : @50} 
                                                  views:views]];
    

    Also, don't use addConstraints: anymore (iOS 8+). Use -[NSLayoutConstraint setActive:] or +[NSLayoutConstraint activateConstraints:]

    As for changing view2's size, you can't set views' frames directly when you're using Auto Layout. The value will be overwritten on the next layout pass. You should create an explicit width constraint for the view:

    [NSLayoutConstraint constraintWithItem:view2
                                 attribute:NSLayoutAttributeWidth
                                 relatedBy:NSLayoutRelationEqual
                                    toItem:nil
                                 attribute:NSLayoutAttributeNotAnAttribute
                                multiplier:1.0
                                  constant:120];
    

    and then adjust that constraint's constant when you need to change the view's size.