Wednesday, October 15, 2014

How To Make an iOS Label Grow Automatically

Introduction

iOS label controls can be configured to autoshrink. This automatically reduces the size of the font used to draw them to fit the text assigned to them into their frame. Their frame is the bounding rectangle they are drawn into. The size of the frame can be set in Interface Builder using constraints.

In this article I am going to describe my attempt to make an Autogrow label. My goal is to create a label that automatically increases its font size so that the text assigned to it fills its frame.
The method I am going to use is to set the label's font size to the maximum allowed by Interface Builder and enable autoshrink. My hope is that the font will then be shrunk until the text just fits in the frame.
This is a three step process:

1. Use constraints to set the size of the label to be relative to the size of the view.
2. Set the label's autoshrink attributes.
3. Increase the label's font size.


Creating a Test Project

All this can be done in Interface Builder without having to write any code. To illustrate this I am going to create a new app project using the Single View Application template. 



I will call my new project AutoGrow.



Defining the Size of the Label's Frame Using Constraints

Before I can define my label's frame I need to create the label. To do this I am just going to drag a UILabel from the Object library onto my view in Interface Builder.



I can now define my label's frame by setting some constraints. The constraints I am going to set will anchor the labels edges to the margins of the view. This is done using the pin constraint button in Interface Builder. 



Here I have set the constraints so that the label's top, bottom, and sides are 0 pixels from the view's margins. I could have set an offset from those margins. However I did not because there is no automatic way to make those offsets proportional to the size of the view. When I click 'Add 4 constraints' Interface Builder draws the new boundary rectangle as a dotted orange line and highlights the constraints with their current sizes again in orange.


Orange is a warning color in Interface Builder. Here the warning is that the constraints I just set do not match the frame that my label got when it was created. I can also see a small orange warning circle in the object tree to the left of the visual representation of my view.


 When I click on that circle I see an explanation of the problem.



When I click on the orange warning triangle next to the explanation Xcode gives me some options to fix the problem.



The default option changes the label's frame to match its constraints. As this is exactly what I need I am just going to click 'Fix Misplacement'.
The frame of my label now matches its constraints and all the orange warnings disappear.



Enabling Autoshrink

The Autoshrink attribute has three possible values. The default is 'Fixed Font Size' which means the font size is not adjusted automatically.

The second possible value is 'Minimum Font Scale' which requires a secondary value which is a floating point number between 0.0 and 1.0. This represents the percentage difference in font size between the label's defined font size and the minimum it can be reduced too.

The third possible value is 'Minimum Font Size' this also requires a secondary value which is simply the minimum size the font can be automatically reduced too.

To implement Autogrow the Autoshrink attribute needs to be set to the third option 'Minimum Font Size'.  The secondary value can be left at its default value.
I also need to change the Baseline to 'Align Centers' so that the text remains aligned to the label's vertical center when the font is resized. 



Increase the Label's Font Size

The final step is to increase the label's font size. By making this size larger than would fit in the largest frame possible we will get the effect that the font is automatically growing to fill whatever space the label occupies.
Unfortunately there is a problem with this goal. In the version of Xcode I am using (6.0.1) Interface Builder imposes a maximum font size of 300. It is possible to get around this by opening the storyboard as source code and editing the xml directly.


However the font size does not seems to scale consistently if the size is set to more than 200. I am going to admit defeat and limit my Autogrow labels to grow to no more than 200 points. I will set my label's alignment to centered so that this limitation is not so noticeable.

Wrapping Up

This is what my label looks like on the smallest screen supported by iOS8 (iPhone 4s):


This is what the same label looks like on the iPad Air screen:



3 comments:

  1. Thanks for a succinct and clear example. There are very few places on the web that have explained the usage of Autoshrink so well. It's an incredibly powerful feature for making text look consistent across devices.

    ReplyDelete
  2. Good example with very detail. Thank you.

    ReplyDelete
  3. Thanks you for sharing the article. The data that you provided in the blog is informative and effective. Through you blog I gained so much knowledge.

    Digital Marketing Training in Chennai

    Digital Marketing Course in Chennai

    ReplyDelete