Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mimic UIStackView `fill proportionally` layout approach on iOS version prior to 9.0

The iOS 9.0 comes with UIStackView which makes it easier to layout views according to their content size. For example, to place 3 buttons in a row in accordance with their content width you can simply embed them in stack view, set axis horizontal and distribution - fill proportionally.

Stack View Solution

The question is how to achieve the same result in older iOS versions where stack view is not supported.

One solution I came up with is rough and doesn't look good. Again, You place 3 buttons in a row and pin them to nearest neighbors using constraints. After doing that you obviously will see content priority ambiguity error because auto layout system has no idea which button needs to grow / shrink before others.

Content Priority Ambiguity

Unfortunately, the titles are unknown before app's launch so you just might arbitrary pick a button. Let's say, I've decreased horizontal content hugging priority of middle button from standard 250 to 249. Now it'll grow before other two. Another problem is that left and right buttons strictly shrink to their content width without any nice looking paddings as in Stack View version.

Layout Comparsion

like image 865
Yakiv Kovalskyi Avatar asked Oct 17 '15 11:10

Yakiv Kovalskyi


1 Answers

It seems over complicated for a such simple thing. But the multiplier value of a constraint is read-only, so you'll have to go the hard way.

I would do it like this if I had to:

  1. In IB: Create a UIView with constraints to fill horizontally the superView (for example)

  2. In IB: Add your 3 buttons, add contraints to align them horizontally.

  3. In code: programmatically create 1 NSConstraint between each UIButton and the UIView with attribute NSLayoutAttributeWidth and multiplier of 0.33.

Here you will get 3 buttons of the same width using 1/3 of the UIView width.

  1. Observe the title of your buttons (use KVO or subclass UIButton). When the title changes, calculate the size of your button content with something like :

    CGSize stringsize = [myButton.title sizeWithAttributes: @{NSFontAttributeName: [UIFont systemFontOfSize:14.0f]}];

  2. Remove all programmatically created constraints.

  3. Compare the calculated width (at step 4) of each button with the width of the UIView and determine a ratio for each button.

  4. Re-create the constraints of step 3 in the same way but replacing the 0.33 by the ratios calculated at step 6 and add them to the UI elements.

like image 183
Xvolks Avatar answered Sep 23 '22 21:09

Xvolks