为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

largeQ 2019-06-20 16:36:56
在UILabel的NSAttributedString中创建可点击的“链接”?我已经找了好几个小时了,但我失败了。我可能都不知道该找什么了。许多应用程序都有文本,在这篇文章中,Web超链接是四舍五入的RECT。当我点击它们UIWebView打开。令我困惑的是,它们通常都有自定义链接,例如,如果单词以#开头,它也是可点击的,应用程序通过打开另一个视图来响应。我怎么能这么做?有没有可能UILabel还是我需要UITextView还是别的什么?
查看完整描述

3 回答

?
ibeautiful

TA贡献1993条经验 获得超5个赞

一般来说,如果我们想在UILabel显示的文本中有一个可点击的链接,我们需要解决两个独立的任务:

  1. 更改部分文本的外观,使其看起来像链接
  2. 检测和处理链接上的触摸(打开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/"]];
    }}


查看完整回答
1 反对 回复 2019-06-20
  • 3 回答
  • 0 关注
  • 2860 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信