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.
I'm working in Swift 3 (iOS 10), so I converted dev_jac's answer for those who need it:
override func drawText(in rect: CGRect) {
var newRect = rect
if (textAlignment == .center) {
let oneLineRect = self.textRect(forBounds: CGRect.infinite, limitedToNumberOfLines: 1)
let numLines = ceil(oneLineRect.size.width / self.bounds.size.width)
var betterWidth : CGFloat = oneLineRect.size.width / numLines
if (betterWidth < rect.size.width) {
var check = CGRect.zero
repeat {
betterWidth *= 1.1
let b = CGRect(x: 0, y: 0, width: betterWidth, height: CGRect.infinite.size.height)
check = self.textRect(forBounds: b, limitedToNumberOfLines: 0)
} while (check.size.height > rect.size.height && betterWidth < rect.size.width)
if betterWidth < rect.size.width {
let difference : CGFloat = rect.size.width - betterWidth
newRect = CGRect(x: rect.origin.x + difference/2, y: rect.origin.y, width: betterWidth, height: rect.size.height)
}
}
}
super.drawText(in: newRect)
}
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!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With