2
votes

The Goal

I am trying to achieve the following design with auto-layout constraints:

enter image description here

What I've Tried

The middle label is straightforward (Horizontally Center to view).

The left and right labels are not as straightforward. Simply adding Leading and Trailing Space constraints of 20 will not work for all content. Furthermore, the detail label underneath can be wider.

I thought about give the right and left labels both Leading and Trailing Space constraints of >= 20 and centering the text.

The Question

How can I achieve this column layout of 3 labels with dynamic content while:

  • ensuring they have at least 20pt of padding between each other
  • ensuring the left and right labels are inset more than 20pts for smaller content
4

4 Answers

5
votes

There's an example for creating equally-spaced views in the Auto Layout Programming Guide. The method is to create invisible "spacer" views between the views you want spaced (and also on the edges) and set the spacers widths using Auto Layout. The width (or height for vertically spaced views) of the spacers are set to be equal. From the PG:

To space views proportionally
1. Create the visible views.
2. Create the spacer views equal to the number of visible views plus one.
3. Alternate placing your views, starting with a spacer view.
To space two visible views, place all of the views in the following pattern, starting from the left side of the screen and moving right:
spacer1 | view1 | spacer2 | view2 | spacer3.
4. Constrain the spacer views so that their lengths are equal to each other.
5. Create a leading constraint from the first spacer view to the container view.
6. Create a trailing constraint from the last spacer view to the container view.
7. Create constraints between the spacer views and the visible views.

1
votes

There are a couple of ways to approach this.

  1. You can give your labels a fixed width, and center align the text (this will be easier to do in interface builder than the other solution). If you make each label equally sized, and pin the edges to each other, this will give you what you want. You don't need any spacing, unless your content is likely to fill the label - in which case, the second solution is better.
  2. The other option is to pin the center of each label to the center of the superview, but use a multiplier - so for the left label, a multiplier of 0.5, the centre, a multiplier of 1.0 and the right label, a multiplier of 1.5. Currently you can only do this in code, but a new version of Xcode is on the way...
0
votes

You could wrap big percent label and corresponding detail label into a wrapper view and make that wrapper view be sized with it's content, then just lay this three wrapper views in a line with the 20px paddings.

        -.-.-.-.           -.-.-.           -.-.-.-.
- (20) -| 100% | - (20) -  |100%| - (20) -  | 100% | - (20) -  
        |detail|           | d  |           |detail|
        -.-.-.-.           -.-.-.           -.-.-.-.

That's just one of the solutions, straightforward one.

0
votes

I solved it by creating outlets for the constraints separating the labels (in my case, margin was fixed).

I did:

let constant = (constraint1to2.constant + constraint2to3.constant)/2
constraint1to2.constant = constant
constraint2to3.constant = constant