0
votes

Imagine the case where you have three buttons side by side. You want the three buttons to fill the available width, and be perfect squares with a minimum size set, with a set amount of space between them. To set this up, you would have the following constraints:

A:
1:1 Ratio to A
Leading to superview
Width and height >= 25

B:
Equal width and height to A
Leading to A: 50

C:
Equal width and height to A
Leading to B: 50
Trailing to superview

Now imagine the available width is small enough such that there isn't enough horizontal space in order to ensure the buttons are a perfect square with 50 between each of them. Instead of breaking the aspect ratio and width constraint, you would instead like to decrease the amount of space between the buttons. My question is, how do you do that?

I thought I would just change the relation of the leading constraints to be less than or equal, but this results in Inequality Constraint Ambiguity with those two constraints. I figured perhaps I need to specify a minimum value for leading, so I added two more leading constraints set to be greater than or equal to 10. That didn't resolve the ambiguity. I then added another set of leading constraints, this time equal to a set value that is in-between the two values, then I decreased the priority of those. This resolved the ambiguity, however the space between the buttons is never decreased - it's always the value I set for the constraint with the equals constraint despite its lowered priority.

What constraints need to be set to obtain this?

  • Three buttons displayed side by side in the same horizontal space
  • All three buttons are perfect squares
  • A minimum size for the buttons (25x25)
  • A set amount of space between them - 50
  • When the horizontal space is too small to ensure the constraints can all be satisfied, it should decrease the amount of space between the buttons.
3

3 Answers

1
votes

You would want a spacing constraint at required priority that expresses the minimum allowed spacing. For example, >= 10 @1000.

Then, you would want a spacing constraint at a lower priority that expresses the desired spacing with an equality, such as == 50 @200.

However, you have two inter-button spaces. The ambiguity comes because auto layout doesn't know which to reduce when there's not enough space available to make both the desired distance.

You could set differing priorities to resolve the ambiguity, but then one spacing would collapse while the other remains at 50, until it reaches its minimum, at which point the other would reduce, too.

I suspect you want both spaces to always be equal. There's no direct way to do that with just constraints. Instead, you need to use hidden spacer views. So, you would do something like:

|-[buttonA][spacer1(>=10,==50@200)][buttonB(==buttonA)][spacer2(==spacer1)][buttonC(==buttonA)]-|
0
votes

Try making the content mode for each button UIViewContentModeScaleAspectFit or whatever IB calls it. Then control the space between using the width instead of leading. I'd guess that tapping the space between would call the button's target, so in that case use three regular UIViews this way and then add the buttons as subviews of them.

0
votes

I ultimately decided to avoid spacer views and worked out a solution to achieve the end result. Instead of setting it up so auto layout would figure out the calculations and automatically decrease the space between buttons, I decided to programmatically set the constant of those constraints based on the view's width. Thus ensuring the space between buttons was large for large widths and small for small widths.

To accomplish this I simply set up an outlet collection for the horizontal constraints, then in updateViewConstraints I looped over the constraints and set the constant equal to self.view.frame.size.width / 12.