Underline text in UIlabel
How can I underline a text that could be multiple lines of string? I find some people suggest UIWebView, but it is obviously too heavy a class for just text rendering.
My thoughts was to figure out the start point and length of each string in each line. And draw a line under it accordingly.
I meet problems at how to figure out the length and start point for the string.
I tried to use -[UILabel textRectForBounds:limitedToNumberOfLines:]
, this should be the drawing bounding rect for the text right?
Then I have to work on the alignment?
How can I get the start point of each line when it is center-justified and right justified?
Solution 1:
You may subclass from UILabel and override drawRect method:
- (void)drawRect:(CGRect)rect {
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSetRGBStrokeColor(ctx, 207.0f/255.0f, 91.0f/255.0f, 44.0f/255.0f, 1.0f); // RGBA
CGContextSetLineWidth(ctx, 1.0f);
CGContextMoveToPoint(ctx, 0, self.bounds.size.height - 1);
CGContextAddLineToPoint(ctx, self.bounds.size.width, self.bounds.size.height - 1);
CGContextStrokePath(ctx);
[super drawRect:rect];
}
UPD:
As of iOS 6 Apple added NSAttributedString support for UILabel, so now it's much easier and works for multiple lines:
NSDictionary *underlineAttribute = @{NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle)};
myLabel.attributedText = [[NSAttributedString alloc] initWithString:@"Test string"
attributes:underlineAttribute];
If you still wish to support iOS 4 and iOS 5, I'd recommend to use TTTAttributedLabel rather than underline label manually. However if you need to underline one-line UILabel and don't want to use third-party components, code above would still do the trick.
Solution 2:
In Swift:
let underlineAttriString = NSAttributedString(string: "attriString",
attributes: [NSAttributedString.Key.underlineStyle: NSUnderlineStyle.single.rawValue])
label.attributedText = underlineAttriString
Solution 3:
This is what i did. It works like butter.
1) Add CoreText.framework to your Frameworks.
2) import <CoreText/CoreText.h> in the class where you need underlined label.
3) Write the following code.
NSMutableAttributedString *attString = [[NSMutableAttributedString alloc] initWithString:@"My Messages"];
[attString addAttribute:(NSString*)kCTUnderlineStyleAttributeName
value:[NSNumber numberWithInt:kCTUnderlineStyleSingle]
range:(NSRange){0,[attString length]}];
self.myMsgLBL.attributedText = attString;
self.myMsgLBL.textColor = [UIColor whiteColor];
Solution 4:
Use an attribute string:
NSMutableAttributedString* attrString = [[NSMutableAttributedString alloc] initWithString:@"Your String"]
[attrString addAttribute:(NSString*)kCTUnderlineStyleAttributeName
value:[NSNumber numberWithInt:kCTUnderlineStyleSingle]
range:(NSRange){0,[attrString length]}];
And then override the label - (void)drawTextInRect:(CGRect)aRect and render the text in something like:
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSaveGState(ctx);
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attrString);
drawingRect = self.bounds;
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path, NULL, drawingRect);
textFrame = CTFramesetterCreateFrame(framesetter,CFRangeMake(0,0), path, NULL);
CGPathRelease(path);
CFRelease(framesetter);
CTFrameDraw(textFrame, ctx);
CGContextRestoreGState(ctx);
Or better yet instead of overriding just use the OHAttributedLabel created by Olivier Halligon