Using autolayout on iOS how can I specify that a view should take up as much space as possible?

13,525

Solution 1

You're going to have to specify additional constraints on the view in order to get it to size the view to fill the remaining available space. Currently, you are setting the view minimums and maximums, but not setting any concrete constraints to give autolayout a more complete solution. In addition to the upper bound for the width, you need to give it 1. a starting point to solve the width for the view by either explicitly giving it a width at a lower priority, or 2. give the spacing on either side some more rigid constraints.

Based on what you've described, you need to constrain your view to give it some more substantial bindings to the superview on either side in order to let the system solve for the width. Since you would like to have the view size itself based on it's container's size, you will need to modify the spacing constraints (option 2 from above). In the above instance, you have specified only a minimum spacing, which would result in any of the following constraint solutions being found as valid by the autolayout engine for a 400pt superview:

|-32pt-[20pt]-------348pt-| <-- autolayout will probably choose this one
|-100pt----[20pt]---280pt-|
|-50pt--[20pt-]-----330pt-|

Which is probably not what you are wanting. Even more still, the width of the view can be anything between 0-576pt, which is also probably not what you're wanting. Since autolayout doesn't know what you want, it's simply using the intrinsicContentSize of the view for concrete sizing constraints. Since you chose 32pt as the spacing, a first step would be to give the spacing constraints some more substantial instructions, namely, telling the system that the spacing should be 32pts between the edges of the view and the superview unless the width of the view is >576pts. You would do this like so in your VFL string:

"H:|-(>=32,==32@900)-[viewToAdd(<=576)]-(>=32,==32@900)-|"

This says: "viewToAdd should have a maximum width of 576pts and have padding between itself and it's superview of 32pts. If the size of the superview grows beyond the maximum width of viewToAdd plus the initial padding of 64pts, the padding on either side should grow in order to continue to solve the constraint set."

This results in the following constraints being correct for a 400pt superview:

|-32pt--[336pt]--32pt-|

If you would like for viewToAdd to remain centered in it's superview when the view grows beyond the maximum, you will have to pass in the option NSLayoutFormatAlignAllCenterX to the options parameter in [NSLayoutConstraint -constraintsWithVisualFormat:]. If you did not have the >=32 constraint set on the padding, or did not set a priority lower than 1000 ("required" constraint priority level) on your padding's ==32 constraint, then your superview would be unable to grow beyond 640pts.

Solution 2

Not sure if this exactly answers the question, but for the ones using Storyboard: I found that you can add a width-constraint and constraints for both the distance to the left and right side of the parent view for example. If you then change the width-constraint to '<=' instead of '=' and set the priority of the distance constraints (both leading and trailing) to 750, the view will max out to the max width, respecting the distance-constraints if the view is too small.

The constraints in place

Share:
13,525

Related videos on Youtube

simon
Author by

simon

Updated on September 16, 2022

Comments

  • simon
    simon over 1 year

    I am using autolayout in iOS to try and build a layout with fluid widths. The visual format for the constraint I am currently using is:

    [self.scrollViewContainer addConstraints:[NSLayoutConstraint 
         constraintsWithVisualFormat:@"H:|-(>=32)-[viewToAdd(<=576)]-(>=32)-|" 
                             options:0 
                             metrics:nil  
                               views:NSDictionaryOfVariableBindings(viewToAdd)
    ]];
    

    That is to say: I want a minimum of 32px spacing on either side, and I want the viewToAdd to have a maximum width of 576px. This works well except that I want the viewToAdd to use up any available space while still meeting all the constraints. Currently I get the viewToAdd only ever being as wide as its intrinsic content size, and the spacing growing as needed.

    Is there a way to specify that the viewToAdd should be as large as possible?

  • larsacus
    larsacus over 11 years
    It also appears I may not have been correct in saying that you can simply pass the option NSLayoutFormatAlignAllCenterX to the visual format and have it center the view in the superview. The options will only apply to views you have explicitly referenced in the visual format string. So it looks like you'll have to have another explicit constraint that constraints the view's center to the superview's center.
  • simon
    simon over 11 years
    Yep thanks - I had actually already centred it in a seperate constraint: [self.scrollViewContainer addConstraint:[NSLayoutConstraint constraintWithItem:viewToAdd attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.scrollViewContainer attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0.0]];