许多应用程序都有文本,文本中是圆角矩形的web超链接,当我点击它们时,UIWebView就会打开。让我困惑的是,他们经常有自定义链接,例如,如果单词以#开头,它也是可点击的,应用程序通过打开另一个视图来响应。我该怎么做呢?是否可以用UILabel或者我需要UITextView或者其他什么?


当前回答

UIButtonTypeCustom是一个可点击的标签,如果你没有为它设置任何图像。

其他回答

我遵循这个版本,

斯威夫特4:

import Foundation

class AELinkedClickableUILabel: UILabel {

    typealias YourCompletion = () -> Void

    var linkedRange: NSRange!
    var completion: YourCompletion?

    @objc func linkClicked(sender: UITapGestureRecognizer){

        if let completionBlock = completion {

            let textView = UITextView(frame: self.frame)
            textView.text = self.text
            textView.attributedText = self.attributedText
            let index = textView.layoutManager.characterIndex(for: sender.location(in: self),
                                                              in: textView.textContainer,
                                                              fractionOfDistanceBetweenInsertionPoints: nil)

            if linkedRange.lowerBound <= index && linkedRange.upperBound >= index {

                completionBlock()
            }
        }
    }

/**
 *  This method will be used to set an attributed text specifying the linked text with a
 *  handler when the link is clicked
 */
    public func setLinkedTextWithHandler(text:String, link: String, handler: @escaping ()->()) -> Bool {

        let attributextText = NSMutableAttributedString(string: text)
        let foundRange = attributextText.mutableString.range(of: link)

        if foundRange.location != NSNotFound {
            self.linkedRange = foundRange
            self.completion = handler
            attributextText.addAttribute(NSAttributedStringKey.link, value: text, range: foundRange)
            self.isUserInteractionEnabled = true
            self.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(linkClicked(sender:))))
            return true
        }
        return false
    }
}

电话的例子:

button.setLinkedTextWithHandler(text: "This website (stackoverflow.com) is awesome", link: "stackoverflow.com") 
{
    // show popup or open to link
}

UITextView支持OS3.0中的数据检测器,而UILabel不支持。

如果你在UITextView上启用了数据检测器,并且你的文本包含url、电话号码等,它们将以链接的形式出现。

- (BOOL)didTapAttributedTextInLabel:(UILabel *)label inRange:(NSRange)targetRange{
    NSLayoutManager *layoutManager = [NSLayoutManager new];
    NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:CGSizeZero];
    NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:label.attributedText];

    [layoutManager addTextContainer:textContainer];
    [textStorage addLayoutManager:layoutManager];

    textContainer.lineFragmentPadding = 0.0;
    textContainer.lineBreakMode = label.lineBreakMode;
    textContainer.maximumNumberOfLines = label.numberOfLines;
    CGSize labelSize = label.bounds.size;
    textContainer.size = labelSize;

    CGPoint locationOfTouchInLabel = [self locationInView:label];
    CGRect textBoundingBox = [layoutManager usedRectForTextContainer: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);
    NSUInteger indexOfCharacter =[layoutManager characterIndexForPoint:locationOfTouchInTextContainer inTextContainer:textContainer fractionOfDistanceBetweenInsertionPoints:nil];

    return NSLocationInRange(indexOfCharacter, targetRange);
}

我创建了一个名为ResponsiveLabel的UILabel子类,它是基于ios7中引入的textkit API。它使用了NAlexN建议的相同方法。它提供了在文本中指定搜索模式的灵活性。可以指定应用于这些模式的样式,以及在敲击模式时要执行的操作。

//Detects email in text

 NSString *emailRegexString = @"[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,4}";
 NSError *error;
 NSRegularExpression *regex = [[NSRegularExpression alloc]initWithPattern:emailRegexString options:0 error:&error];
 PatternDescriptor *descriptor = [[PatternDescriptor alloc]initWithRegex:regex withSearchType:PatternSearchTypeAll withPatternAttributes:@{NSForegroundColorAttributeName:[UIColor redColor]}];
 [self.customLabel enablePatternDetection:descriptor];

如果你想让一个字符串可点击,你可以这样做。这段代码将属性应用到字符串“text”的每个出现处。

PatternTapResponder tapResponder = ^(NSString *string) {
    NSLog(@"tapped = %@",string);
};

[self.customLabel enableStringDetection:@"text" withAttributes:@{NSForegroundColorAttributeName:[UIColor redColor],
                                                                 RLTapResponderAttributeName: tapResponder}];

对于完全自定义的链接,你需要使用UIWebView -你可以拦截调用,这样当链接被按下时,你可以转到应用程序的其他部分。