Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 334
simon Avatar asked Oct 30 '12 04:10

simon


People also ask

How do you add constraints in storyboard IOS?

Open the Align menu with the yellow button selected and check Horizontally in Container, then click Add 1 Constraint. Now, select both buttons at the same time using the Shift key and, in the Align menu, check Leading Edges. Again, actually install the constraint by clicking Add 1 Constraint.

How do I create a constraint in Autolayout?

To create constraints select the button and click the Align icon in the auto layout menu. A popover menu will appear, check both “Horizontal in container” and “Vertically in container” options to center the button on the screen. Then click the “Add 2 Constraints” button. Run the application.

How do you use intrinsic content size?

An ExampleOpen the Object Library on the right and add a label to the View Controller Scene. Select the label and center it horizontally and vertically in its superview using the Align menu at the bottom. With the label selected, open the Attributes Inspector and set the text of the label to Intrinsic Content Size.

What is intrinsic content size IOS?

Intrinsic content size is information that a view has about how big it should be based on what it displays. For example, a label's intrinsic content size is based on how much text it is displaying. In your case, the image view's intrinsic content size is the size of the image that you selected.


2 Answers

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.

like image 82
larsacus Avatar answered Oct 17 '22 10:10

larsacus


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

like image 31
Tum Avatar answered Oct 17 '22 09:10

Tum