rdurand rdurand - 2 months ago 17
iOS Question

Balance multi line UILabel

When I create a

UILabel
with
textAlignement
set to
NSTextAlignmentCenter
,
lineBreakMode
to
NSLineBreakByWordWrapping
and a long text, it splits like this :

+------------------------------------+
| Text that does not fit on a single |
| line |
+------------------------------------+


But what I really want is something like this :

+------------------------------------+
| Text that does not fit |
| on a single line |
+------------------------------------+


Of course, I don't want to handle the line break manually. I want the label to automatically balance the lines so their lengths are as close as possible.

Answer

I had the same issue and inspired by this question I found a solution by just overriding - (void)drawTextInRect:(CGRect)rect

You can see it in this GitHub Project

The method itself if you just want to copy / read it is here

- (void)drawTextInRect:(CGRect)rect {
    if (self.textAlignment == NSTextAlignmentCenter) {
        CGRect oneLineRect = [self textRectForBounds:CGRectInfinite limitedToNumberOfLines:1];
        NSInteger numberOfLines = ceil(oneLineRect.size.width / self.bounds.size.width);
        CGFloat betterWidth = (oneLineRect.size.width / numberOfLines);
        if (betterWidth < rect.size.width) {
            CGRect check = CGRectZero;
            do {
                betterWidth *= 1.1;
                CGRect b = CGRectMake(0, 0, betterWidth, CGRectInfinite.size.height);
                check = [self textRectForBounds:b limitedToNumberOfLines:0];
            } while (check.size.height > rect.size.height && betterWidth < rect.size.width);

            if (betterWidth < rect.size.width) {
                CGFloat difference = rect.size.width - betterWidth;
                rect = CGRectMake(rect.origin.x + difference/2.0, rect.origin.y, betterWidth, rect.size.height);
            }
        }
    }
    [super drawTextInRect:rect];
}

PR, forks, comments are welcome!

Comments