在UILabel的NSAttributedString中创建可点击的“链接”?

在UILabel的NSAttributedString中创建可点击的“链接”?

我已经找了好几个小时了,但我失败了。我可能都不知道该找什么了。

许多应用程序都有文本,在这篇文章中,Web超链接是四舍五入的RECT。当我点击它们UIWebView打开。令我困惑的是,它们通常都有自定义链接,例如,如果单词以#开头,它也是可点击的,应用程序通过打开另一个视图来响应。我怎么能这么做?有没有可能UILabel还是我需要UITextView还是别的什么?


largeQ
浏览 2969回答 3
3回答

ibeautiful

一般来说,如果我们想在UILabel显示的文本中有一个可点击的链接,我们需要解决两个独立的任务:更改部分文本的外观,使其看起来像链接检测和处理链接上的触摸(打开URL是一种特殊情况)第一个很简单。从iOS 6开始,UILabel支持显示属性字符串。您所需要做的就是创建和配置NSMutableAttributedString实例:NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:@"String with a link" attributes:nil]; NSRange linkRange = NSMakeRange(14, 4); // for the word "link" in the string aboveNSDictionary *linkAttributes =  @{ NSForegroundColorAttributeName : [UIColor colorWithRed:0.05 green:0.4 blue:0.65 alpha:1.0],                                   NSUnderlineStyleAttributeName : @(NSUnderlineStyleSingle) };                                   [attributedString setAttributes:linkAttributes range:linkRange];                                   // Assign attributedText to UILabellabel.attributedText = attributedString;就这样!上面的代码使UILabel显示字符串具有链接现在我们应该检测到这个链接的触点。这样做的目的是捕捉UILabel中的所有点击,并确定点击的位置是否足够接近链接。为了捕捉触摸,我们可以添加点击手势识别器到标签。确保为标签启用userInteraction,默认情况下它被关闭:label.userInteractionEnabled = YES;[label addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget: self action:@selector(handleTapOnLabel:)]];现在,最复杂的东西:找出点击是否在链接显示的位置,而不是在标签的任何其他部分。如果我们有单行UILabel,这个任务可以通过硬编码显示链接的区域边界来相对容易地解决,但是让我们更优雅地解决这个问题,对于一般情况-多行UILabel,不需要对链接布局有初步的了解。其中一种方法是使用IOS 7中引入的文本工具包API的功能:// Create instances of NSLayoutManager, NSTextContainer and NSTextStorageNSLayoutManager *layoutManager = [[NSLayoutManager alloc] init]; NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:CGSizeZero];NSTextStorage *textStorage = [[NSTextStorage alloc]  initWithAttributedString:attributedString];// Configure layoutManager and textStorage[layoutManager addTextContainer:textContainer]; [textStorage addLayoutManager:layoutManager];// Configure textContainertextContainer.lineFragmentPadding = 0.0;textContainer.lineBreakMode  = label.lineBreakMode;textContainer.maximumNumberOfLines = label.numberOfLines;在类中的属性中保存已创建和配置的NSLayoutManager、NSTextContainer和NSTextStorage实例(很可能是UIViewController的后代)-我们将在其他方法中使用它们。现在,每当标签更改其框架时,更新TextContainer的大小:- (void)viewDidLayoutSubviews{     [super viewDidLayoutSubviews];     self.textContainer.size = self.label.bounds.size;}最后,检测点击是否正好在链接上:- (void)handleTapOnLabel:(UITapGestureRecognizer *)tapGesture{     CGPoint locationOfTouchInLabel = [tapGesture locationInView:tapGesture.view];     CGSize labelSize = tapGesture.view.bounds.size;     CGRect textBoundingBox = [self.layoutManager usedRectForTextContainer:self.textContainer];     CGPoint textContainerOffset = CGPointMake((labelSize.width - textBoundingBox.size.width) * 0.5 - textBoundingBox.origin.x,                                                                            (labelSize.height - textBoundingBox.size.height) * 0.5 - textBoundingBox.origin.y);     CGPoint locationOfTouchInTextContainer = CGPointMake(locationOfTouchInLabel.x - textContainerOffset.x,                                                          locationOfTouchInLabel.y - textContainerOffset.y);     NSInteger indexOfCharacter = [self.layoutManager characterIndexForPoint:locationOfTouchInTextContainer                                                             inTextContainer:self.textContainer                                    fractionOfDistanceBetweenInsertionPoints:nil];     NSRange linkRange = NSMakeRange(14, 4);      // it's better to save the range somewhere when it was originally used for marking link in attributed string     if (NSLocationInRange(indexOfCharacter, linkRange)) {         // Open an URL, or handle the tap on the link in any other way         [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"https://stackoverflow.com/"]];     }}
打开App,查看更多内容
随时随地看视频慕课网APP