Using Autolayout to Dynamically Resize UILabel

We all love Autolayout, don't we? I had a less than ideal experience with it when I started. However, after continuous practice and reading a Book - iOS Auto Layout Demystified I got more comfortable with it. However, there are certain cases where it's still possible to solve problem with Auto layout, but it takes time to figure out correct thing to do.

In this post, I will go through few situations where we want grow UILabel as per the content and with additional constraints so that it remains in bounds and will not outgrow its boundary.

Let's go through some of these scenarios and how we can fix them with auto layout.

  1. Fixed width, adjustable height
    This is the use case where UILabel content is variable. We want to keep the width fixed, but make height variable. Width can either be constrained to both ends or kept fixed in terms of fixed number for width.

    For all the scenarios described in this post, we will not simply use UILabel, but UILabel added as a subView to UIView. Let's first add a UIView to a scene and add following constraints to it.

    • Align leading edge to superView
    • Align trailing edge to superView
    • Align top to superView
    • Since we want height to be variable, add constraint for height and make it greater than or equal to. So that the height constraint you provided represents the minimum height that label can have. For our example, we will assume minimum height UIView can have is 20px

    Now add UILabel as a subView of this view and add following constraints with respect to superView.

    • Align leading edge to superView with 10px padding
    • Align trailing edge to superView with 10px padding
    • Align top edge to superView with 10px padding
    • Align bottom edge to superView with 10px padding
    • Also add a constraint for height to restrain height greater than or equal to zero. This will ensure that UILabel will grow as per the content, but also reduces height to zero if there is no content available.
    • Make numberOfLines parameters to zero. This will ensure that UILabel stretches vertically

    You can also color individual views in order to see how they resize as per the content they host

    After you've added all the required constraints, it will look like following on storyboard

    For UILabel

    Screen-Shot-2017-10-08-at-3.38.10-PM

    For UIView

    Screen-Shot-2017-10-08-at-3.38.03-PM

    Let's fill the UILabel with unreasonably long text to see how that will work and run the project and see how that looks in the simulator. With text of reasonable size, you will from screen shot below that UILabel and UIView have grown vertically to accommodate text keeping width fixed.

    Screen-Shot-2017-10-08-at-3.40.48-PM

    With less text,

    Screen-Shot-2017-10-08-at-5.00.58-PM

    With no text,

    Screen-Shot-2017-10-08-at-5.01.20-PM

    Please keep in mind that the way constraints are set up for this example, UILabel or UIView will not be able to adjust the size in horizontal direction. That is, even if you have text that does not fill the entire width, unfilled portion of views will remain blank

  2. Fixed height, variable width
    In this case, UILabel width grows as per the content. (Keeping in mind any additional padding it may have with respect to other views).

    However, height remains the same. Additionally you can place constraints on container UIView so that it does not quite touch the views boundary.

    One of the examples where such cases can be used it when you have a tableView/collectionView cell and you want to show the banner in either corner where banner stretches horizontally as per the content, but never grows vertically. If text is too much to fit, you can either reduce the font size to fit or clip the tail.

    Like previous example, we will add UIView and embed UILabel inside it.

    Constraints for UIView:

    • Align leading edge with superView
    • Align top edge with superView
    • Constraint for fixed height of 60px
    • A constraint for trailing edge. It specifies the spacing between this view and superView should be greater than or equal to 50px. This is our padding with respect to right edge
    • The last constraint will make sure UIView stretches with the content of UILabel it hosts.

    Screen-Shot-2017-10-08-at-4.13.08-PM

    Constraints for UILabel:

    • Add UILabel as a subView of previously added UIView
    • Let the parameter numberOfLines remain to 1. This will make sure UILabel won't stretch vertically
    • Add constraints for leading, trailing, top and bottom edges with 10px padding for each

    Screen-Shot-2017-10-08-at-4.13.15-PM

    Now, let's add some content to test our assumption and constraints.

    With less text,

    Screen-Shot-2017-10-08-at-4.21.03-PM

    With more text

    Screen-Shot-2017-10-08-at-4.23.46-PM

    Thus, we have successfully added the UILabel which stretched horizontally with the text content, does not grow vertically and has an additional horizontal padding on either side

  3. Variable width and variable height
    This is slightly more complicated case compared to earlier cases we discussed. It combines both aspects of previous discussions. Variable width and variable height.

    Let's start with base UIView which will act as a container for final UILabel. We add following constraints to it.

    • Leading edge constraint with respect to superView
    • Trailing edge constraint with respect to superView with 50px padding on the end
    • Height constraint for height to be minimum 20px. This is to accommodate 10px padding enclosing UILabel is going to have on top and bottom
    • Bottom alignment to superView
    • A constraint for width to be greater than or equal to zero. This will ensure that UIView width reduced to zero if enclosing UILabel has no text on it

    And now, the Constraints for UILabel

    • Trailing padding of 10px to superView
    • Leading padding of 10px to superView
    • Top padding of 10px to superView
    • Bottom padding of 10px to superView
    • A constraint for width to be greater than or equal to zero. This will ensure that UILabel width is reduced to zero if it has no text content
    • A constraint for height to be greater than or equal to zero. This will ensure that UILabel height is reduced to zero if it has no text content
    • Set numberOfLines to zero for UILabel. This will ensure that label will stretch vertically with the text content in it

    After all the constraints have been added it will look like this on the storyBoard

    Constraints for parent UIView

    Screen-Shot-2017-10-08-at-4.41.18-PM

    Constraints for enclosed UILabel

    Screen-Shot-2017-10-08-at-4.41.25-PM

    Now once all the constraints are added and views are set up, let's test our constraints with few test cases,

    • No text

      Screen-Shot-2017-10-08-at-4.45.48-PM

    • Text that fits properly in horizontal space

      Screen-Shot-2017-10-08-at-4.47.33-PM

    • Text that does not fit in the horizontal space

      Screen-Shot-2017-10-08-at-4.48.23-PM

    • Text that does not fit in the provided horizontal and vertical space

      In this case we decide to clip the content's tail. Alternatively, you can also choose how you want to apply line break - Such as truncate head, middle or by providing minimum font size

      Screen-Shot-2017-10-08-at-4.49.48-PM

This is all I got for today. Autolayout is awesome and with Apple releasing new devices every year, it has become mandatory to use it in every app with support to automatically adjust layout to fit any screen or device. Please let me know if you have further questions about using autolayout for specific use-cases you are building apps for.

This is just the beginning and we have just scratched the surface, If you are interested in more autolayout examples, feel free to clone the Autolayout repo on the Github. It has code examples about tricks we learned in this post and other useful tricks. Pull requests and improvements are welcome too.