How do you make a vertical text UILabel and UITextView for iOS in Swift?

Edit: This is how I finally did it.

Here’s a very basic implementation in my GitHub: Vertical-Text-iOS.

Nothing fancy, but it works. Finally I had to mix TextKit and image processing. Take a look at the code. It involves:

  1. Subclassing NSTextContainer to get the right text dimensions.
  2. Creating a custom UIView to render the text applying affine transformations to each line and rendering using NSLayoutManager to keep all TextKit features.

TextKit way

The proper way to keep all native text benefits (e.g. highlighting, selection…) is to use standard TextKit APIs. The method you are proposing would break all that or would possibly result in strange behaviour.

However, looks like TextKit in iOS does not support vertical orientation out-of-the-box yet, but it is prepared for that. As a side note, in OS X it is somewhat supported and you could call textView.setLayoutOrientation(.Vertical), but it still has some limitations.

The NSTextLayoutOrientationProvider protocol defines an interface
providing the default orientation for text laid out in a conforming
object, in absence of an explicit NSVerticalGlyphFormAttributeName
attribute. The only UIKit class that implements this interface is
NSTextContainer, whose default implementation returns
NSTextLayoutOrientationHorizontal. An NSTextContainer subclass that
handles vertical text could set this property to
NSTextLayoutOrientationVertical to support the custom layout
orientation logic.

Source: UIKit > NSTextLayoutOrientationProvider Protocol Reference for iOS

In conclusion, you should start subclassing NSTextContainer, and you will have to deal with NSLayoutManager and NSTextContainer a lot.


Custom image processing way

If, on the other hand you decide to follow your custom text rendering I suggest the following approach.

  1. Render the normal text to a hidden layer with a normal font. Give it the correct size to its bounding box.
  2. Get the text properties, mainly text height and line spacing.
  3. Process the image drawing each line in reverse order from bottom to top as you can see in the image below. You should get a new CGImage as a result.
  4. Rotate the image creating a UIImage and setting the correct UIImageOrientation value.
  5. Insert that image into a UIScrollView that only allows horizontal scrolling.

Beware this method renders the whole text, so don’t use it for very long texts. If you need to do that, you will need to consider a tiling approach. Watch WWDC 2013 > 217 – Exploring Scroll Views on iOS 7.

this image

Good luck!

Update: (image from github project)

enter image description here

Leave a Comment