Wednesday, January 20, 2016

Autolayout - nicely stacking UILabels that change size with content

Hi folks, first post in this new blog.  This is an overview of how to achieve a nicely stacking set of UILabels using Autolayout, with content for each label that can change on the fly.  So the labels need to be able to expand and contract in height, depending on the content, and all other labels need to shuffle up and down with the changes.  Heres how it looks in the app :



And heres how it looks in Interface Builder :



So the simple effect is that, when in code, the contents of the labels on the right are changed, the UILabels change size, and the other UILabels move down to accommodate the change.  Also though, the key labels on the left move down to stay aligned with the value labels.  Simple you'd think - but there are quite a few steps required to achieve this effect, especially when changing text programmatically.

First the UILabels.  The text needs to be set correctly to allow the label to expand vertically.  There are two settings you need - first, Lines - 0 (which actually means, as many as required); and Line Breaks : Word Wrap.



With autolayout, you need to carefully think about your rules for each object.  Each needs info for x & y, width & height.  So heres the rules for my objects : the left hand 'key' labels remain a constant width and height (80px x 30px).  They are always 0px from the left hand side, and there is always 8px between them and the value labels on the right.  Finally, in terms of y origin, they match the y position of the labels on the right (because only the value labels can change height with text changes), and the key labels need to track the vertical position of the value labels.

For the value labels on the right, the rules are : they are always 8px away from the key label on the left, always 8px from the label above, always 8px from the superview edge on the right, and they have flexible height.

Theres two important facts here : that the key labels don't change width or height, and that only the value labels can change height.  You need to have a certain amount of fixed sizes like this to make constraints work - if for eg my keys on the left also had a flexible width, it would be too many variable width sizes for autolayout, and it would complain (understandably).  So if you can give something a fixed width or height, then do.

First to set the constraints then in IB.  So lets do the right hand value label first - top, left, right, and height :


Now the height is going to be flexible for this label.  So first we set it to fixed (30px - this will be our base value, so the label will not have a height less than this).  To make this flexible, we change it from fixed to 'equal to or greater than'.  To do this, double click on this height constraint in the pane on the right, having first selected the object in IB - this allows us to edit the details of the constraint.



Then click on the 'relation' drop down and select 'greater than or equal to' - this is the cunning expandable height option.



Next we do the key label on the left.  So it adheres to the left, maintains a set width to the label on the right, and has a constant width and height :



And finally, it needs to keep aligned with the y position of its corresponding value label on the right, as these expand downwards.  So we drag from the key label across to the value label, whilst holding down the Ctrl key.  This gives us a handy menu where we can select 'Top' - this adds a constraint that keeps the tops of both labels aligned, and gives us the final y value we need for this key label.  At this point, autolayout has enough info to lay out both labels, so things should go nice and blue, indicating there are no uncertainties in the rules.



Then the final bit - the code.  You can set the contents of these labels in code, and a simple call to setNeedsLayout is all thats required (on the superview) to make it all resize itself correctly.  For eg :


And thats it.  Please post a comment if anything is not clear or missing for you, thanks.


No comments:

Post a Comment

Social Network with Firebase 3 - Infinitely scrolling UITableView of Firebase Items

Ive already talked about the basics of a Firebase social network project , and adding posts in two other articles. Here I want to explain ...