-
Notifications
You must be signed in to change notification settings - Fork 17
link in UILabel
AliSoftware edited this page Jan 21, 2015
·
5 revisions
Here is a suggestion to how to do it:
- Ensure the
userInteractionEnabledproperty of yourUILabelis set toYES - Add an
UITapGestureRecognizeron yourUILabel, and associate it with aselector/IBAction (let's call ithandleLabelTap:) - Implement that callback this way:
- (IBAction)handleLabelTap:(UITapGestureRecognizer *)tapGR
{
// Only execute the rest of the code if the gesture ended (not during its intermediate states)
if (tapGR.state != UIGestureRecognizerStateEnded) return;
// Get the tapped label and the point where the tap occurred in the label
UILabel* label = (UILabel*)tapGR.recognizedView;
CGPoint tapPoint = [tapGR locationInView:label];
// Create the layoutManager & textContainer to compute how characters are positionned
NSLayoutManager *layoutManager = [NSLayoutManager new];
NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:label.attributedText];
[textStorage addLayoutManager:layoutManager];
NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:label.bounds.size];
textContainer.lineFragmentPadding = 0;
textContainer.maximumNumberOfLines = (NSUInteger)label.numberOfLines;
textContainer.lineBreakMode = label.lineBreakMode;
[layoutManager addTextContainer:textContainer];
// ask the layoutManager which character is under this tapped point
NSUInteger charIdx = [layoutManager characterIndexForPoint:tapPoint
inTextContainer:textContainer
fractionOfDistanceBetweenInsertionPoints:NULL];
// the previous method returns the last character if the point is past the last char
// so we ensure the tap is not after the end of the text
CGRect textRect = [layoutManager usedRectForTextContainer:textContainer];
if (CGRectContainsPoint(textRect, tapPoint))
{
// Get the underlying URL.
NSURL* url = [label.attributedText URLAtIndex:charIdx effectiveRange:NULL];
if (url)
{
[self label:label didTapOnURL:url];
}
}
}
- (void)label:(UILabel*)label didTapOnURL:(NSURL*)url
{
// Act accordingly
}You can now set the attributedText property of your UILabel to an NSAttributedString with a link in it:
NSMutableAttributedString* str = [NSMutableAttributedString attributedStringWithString:@"Hello world!"];
NSURL* url = [NSURL URLWithString:@"https://github.com"];
[str setURL:someURL range:NSMakeRange(6,5)];
self.label.attributedText = str;Note: Given this implementation, you can even add more than one
UILabelto your interface and add anUITapGestureRecognizedto each of them with the samehandleLabelTap:action/callback for all of them. Thelabel:didTapOnURL:method will be called if an URL has been tapped on any of those labels and you can test which label and URL to act accordingly.
I will probably add a category on UILabel to propose this code directly in my code some day, in the meantime you can freely copy/paste it directly.