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

前端 未结 2 601
误落风尘
误落风尘 2020-11-28 09:57

If you came to this question based on the title but are not interested in Mongolian, you might be looking for this Q&A instead:

  • Swift: How can you rotate t
相关标签:
2条回答
  • 2020-11-28 10:11

    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

    0 讨论(0)
  • If you're going to rotate the text I would suggest using a right-to-left layout so that you can skip the mirroring step (and just rotate the other way).

    You should be able to just set the label/textview's transform property:

    view.transform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(CGFloat(-M_PI_2)), view.bounds.width, view.bounds.height)
    

    You need to translate after you rotate because the view rotates around its origin (in the upper left).

    The good news is that gestures and taps are transformed at the same time the pixels are, so controls continue to work the way you expect them to.

    0 讨论(0)
提交回复
热议问题