I'd like to flow the text in UILabel
into a circle (instead of rect).
I did some experiments with NSLayoutManager
, NSTextContainer
and NSTextStorage
but it does not seem to work.
The example below is supposed to flow the text into a smaller rect of 40x40 (label is 120x120) but does not seem to have any effect.
UIFont *font = [UIFont fontWithName:@"HelveticaNeue" size:12];
NSTextStorage *ts = [[NSTextStorage alloc] initWithString:multiline.title attributes:@{NSFontAttributeName:font}];
NSLayoutManager *lm = [[NSLayoutManager alloc] init];
NSTextContainer *tc = [[NSTextContainer alloc] initWithSize:CGSizeMake(40, 40)];
[lm addTextContainer:tc];
[ts addLayoutManager:lm];
self.label.attributedText = ts;
Ides?
This appeared to be a very simple solution.
NSTextContainer
has anexclusionPaths
property. What you can do is to create two Bezier paths that will define areas that should be excluded.So I did that and here is my method:
Example usage:
And a result of my experiments:
Of course you will have to use a UITextView instead of UILabel but I hope it helps :)
With Swift 4 and iOS 11,
NSTextContainer
has a property calledexclusionPaths
.exclusionPaths
has the following declaration:Besides,
UIBezierPath
has a property calledusesEvenOddFillRule
.usesEvenOddFillRule
has the following declaration:By using
usesEvenOddFillRule
, you can create an exclusion path surrounding a circle with only a few lines of code:The following
UITextView
andUIViewController
subclasses show how to display text inside a circle usingNSTextContainer
exclusionPaths
andUIBezierPath
usesEvenOddFillRule
properties:TextView.swift
ViewController.swift
By picking one or the other implementation of
draw(_:)
, you will have the following displays:Here is my contribution to the above question in Swift 3. https://github.com/icatmed/ICRoundLabel.git
}
You can't do this in a UILabel because it doesn't give you access to the TextKit stack. What I do is to build my own TextKit stack and subclass NSTextContainer:
Crude but effective. Looks like this: