Custom UILabel with glyph layout

You may have noticed that several popular iOS apps make use of text visual effects to create unique user interfaces and enhance the user experience. Animating the text isn’t a very common thing yet and could help set you app apart in the crowded App Store.

But, as any kind of animation, it should be used intelligently to create subtle effects on certain types of text. It’s not a good idea to animate body text, as it distracts the user from reading the content, but could be used on headers or captions to emphasize the transitions between different content blocks.

Some spectacular effects can be created at the level of the glyph, which is the text unit displayed on screen. If, as me, you are not a graphic designer or a typography expert, here is a concise explanation of the difference between glyphs and characters. To be able to animate each glyph individually, we first have to break the text into multiple CATextLayer objects, each one containing a single glyph.

As I briefly explained in the previous blog post, we are able customize the way the text is laid out on screen using the NSLayoutManager object from the Text Kit stack.

To demonstrate how to create a layer for each glyph and place the layers as shown in the screenshot below, I used the techniques explained in this excellent article by Andrew Hulsizer. His open source code, written in both Swift and Objective-C, shows how to create some spectacular text effects based on glyph animations. The sample code is available on GitHub.

custom position glyph with CATextLayer

Extend UILabel

Unlike UITextView, the standard UILabel class doesn’t have a predefined Text Kit stack composed of NSTextStorage, NSLayoutManager and NSTextContainer instances. We have to create a custom UILabel subclass which instantiates the stack objects in the initializers:

Split the text in glyph layers

Because the text contained in the UILabel is laid out before the Auto Layout system applies the constraints to the label and displays it on screen, we have to specify to the NSLayoutManager the size of the area where it lays out the text. Otherwise it will try to squeeze it in the initial label bounds, before Auto Layout gets the chance to calculate the actual size.

We override the -intrinsicContentSize method and return a CGSize struct slightly larger that the rectangle in which the text should fit. I noticed that, without this small padding, the NSLayoutManager merges the last two characters of the text into a single glyph.

Each time the NSLayoutManager finishes laying out the label content, it notifies its delegate by invoking the method -layoutManager:didCompleteLayoutForTextContainer:atEnd:. In this method, we loop through the glyphs generated from the characters and create a CATextLayer for each glyph. The layer frame is set to the rectangle returned by the NSLayoutManager for each glyph it lays out.

Change the text presentation

We are now able to customize the presentation of each glyph layer in the NSArray returned by the -glyphLayers method.

I added an instance of the custom UILabel to the view controller and attached it to the center of the main view using Auto Layout constraints.

After Auto Layout finishes placing and sizing the subviews, each glyph layer is vertically offset to create the zig-zag effect visible in the previous screenshot. Obviously, it is possible to use Core Animation and do much more interesting things with the CATextLayer objects, but I leave that to you:

Conclusion

I didn’t test the custom UILabel in all the possible use cases and there probably are issues when it is used in different contexts. It certainly can be extended and improved to support other scenarios. But it shows how powerful the Text Kit framework is, allowing developers to draw into the text layout process, access and customize the smallest text components which are the individual glyphs.

 

Catalin Rosioru