如何制作 URL/电话可点击的 UILabel?

Posted

技术标签:

【中文标题】如何制作 URL/电话可点击的 UILabel?【英文标题】:How to make URL/Phone-clickable UILabel? 【发布时间】:2012-05-27 18:13:49 【问题描述】:

我想在我的应用上创建一个可点击的标签,将我引导至 Safari 网页。我还希望用户只能通过单击来拨打电话号码?

感谢您的建议

【问题讨论】:

Create tap-able "links" in the NSAttributedText of a UILabel?的可能重复 【参考方案1】:

您可以使用UITextView 并在检查器中选择检测链接、电话号码和其他内容。

【讨论】:

我有一个可自动调整大小的标签,可以容纳 N 行文本。如何在不实现 UITextView 的情况下使此标签中的链接可点击。 @bibscy 然后你可以使用 NSAttributedText。看***.com/questions/1256887/…【参考方案2】:

使用UITextView 而不是UILabel,它具有将文本转换为超链接的属性。

目标-C:

yourTextView.editable = NO;
yourTextView.dataDetectorTypes = UIDataDetectorTypeAll;

斯威夫特:

yourTextView.editable = false; 
yourTextView.dataDetectorTypes = UIDataDetectorTypes.All;

这将自动检测链接。

详情请见the documentation。

【讨论】:

这会将链接染成蓝色并加下划线,但似乎确实使它可点击,至少在 ios 7 上是这样。 Swift 代码:yourTextView.editable = false; yourTextView.dataDetectorTypes = UIDataDetectorTypes.All; 问题是关于 UILabel,而不是 UITextView。【参考方案3】:

https://github.com/mattt/TTTAttributedLabel

这绝对是您所需要的。您还可以为标签应用属性,例如下划线,并为其应用不同的颜色。只需查看可点击网址的说明即可。

主要是做如下的事情:

NSRange range = [label.text rangeOfString:@"me"];
[label addLinkToURL:[NSURL URLWithString:@"http://github.com/mattt/"] withRange:range]; // Embedding a custom link in a substring

【讨论】:

【参考方案4】:

您可以根据需要制作自定义 UIButton 和 setText 并使用它添加方法。

UIButton *sampleButton = [UIButton buttonWithType:UIButtonTypeCustom];
[sampleButton setFrame:CGRectMake(kLeftMargin, 10, self.view.bounds.size.width - kLeftMargin - kRightMargin, 52)];
[sampleButton setTitle:@"URL Text" forState:UIControlStateNormal];
[sampleButton setFont:[UIFont boldSystemFontOfSize:20]];


[sampleButton addTarget:self action:@selector(buttonPressed) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:sampleButton];


-(void)buttonPressed:(id)sender
  // open url

【讨论】:

现在通过以下方式设置字体:button.titleLabel.font = [UIFont systemFontOfSize:size];【参考方案5】:

如果你想让这个由 UILabel 而不是 UITextView 处理,你可以创建 UILabel 的子类,像这样:

class LinkedLabel: UILabel 

fileprivate let layoutManager = NSLayoutManager()
fileprivate let textContainer = NSTextContainer(size: CGSize.zero)
fileprivate var textStorage: NSTextStorage?


override init(frame aRect:CGRect)
    super.init(frame: aRect)
    self.initialize()


required init?(coder aDecoder: NSCoder) 
    super.init(coder: aDecoder)
    self.initialize()


func initialize()

    let tap = UITapGestureRecognizer(target: self, action: #selector(LinkedLabel.handleTapOnLabel))
    self.isUserInteractionEnabled = true
    self.addGestureRecognizer(tap)


override var attributedText: NSAttributedString?
    didSet
        if let _attributedText = attributedText
            self.textStorage = NSTextStorage(attributedString: _attributedText)

            self.layoutManager.addTextContainer(self.textContainer)
            self.textStorage?.addLayoutManager(self.layoutManager)

            self.textContainer.lineFragmentPadding = 0.0;
            self.textContainer.lineBreakMode = self.lineBreakMode;
            self.textContainer.maximumNumberOfLines = self.numberOfLines;
        

    


func handleTapOnLabel(tapGesture:UITapGestureRecognizer)

    let locationOfTouchInLabel = tapGesture.location(in: tapGesture.view)
    let labelSize = tapGesture.view?.bounds.size
    let textBoundingBox = self.layoutManager.usedRect(for: self.textContainer)
    let textContainerOffset = CGPoint(x: ((labelSize?.width)! - textBoundingBox.size.width) * 0.5 - textBoundingBox.origin.x, y: ((labelSize?.height)! - textBoundingBox.size.height) * 0.5 - textBoundingBox.origin.y)

    let locationOfTouchInTextContainer = CGPoint(x: locationOfTouchInLabel.x - textContainerOffset.x, y: locationOfTouchInLabel.y - textContainerOffset.y)
    let indexOfCharacter = self.layoutManager.characterIndex(for: locationOfTouchInTextContainer, in: self.textContainer, fractionOfDistanceBetweenInsertionPoints: nil)


    self.attributedText?.enumerateAttribute(NSLinkAttributeName, in: NSMakeRange(0, (self.attributedText?.length)!), options: NSAttributedString.EnumerationOptions(rawValue: UInt(0)), using:
        (attrs: Any?, range: NSRange, stop: UnsafeMutablePointer<ObjCBool>) in

        if NSLocationInRange(indexOfCharacter, range)
            if let _attrs = attrs

                UIApplication.shared.openURL(URL(string: _attrs as! String)!)
            
        
    )


这个类是通过重用来自answer 的代码创建的。为了使属性字符串检查这个answer。和here你可以找到如何制作手机网址。

【讨论】:

【参考方案6】:

使用这个我非常喜欢它,因为它只创建了指向特定文本的蓝色链接,而不是整个标签文本:FRHyperLabel

待办事项:

    从以上链接下载并将FRHyperLabel.hFRHyperLabel.m复制到您的项目中。

    UILabel 拖放到您的 Storyboard 中,并在识别检查器中将自定义类名称定义为 FRHyperLabel,如图所示。

    将您的 UILabel 从情节提要连接到您的 viewController.h 文件

@property (weak, nonatomic) IBOutlet FRHyperLabel *label;

    现在在您的 viewController.m 文件中添加以下代码。

`NSString *string = @"上传即表示同意使用条款"; NSDictionary *attributes = @NSFontAttributeName: [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline];

_label.attributedText = [[NSAttributedString alloc]initWithString:string attributes:attributes];
[_label setFont:[_label.font fontWithSize:13.0]];

[_label setLinkForSubstring:@"Terms of Use" withLinkHandler:^(FRHyperLabel *label, NSString *substring)
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"http://www.google.com"]];
];`
    然后运行它。

【讨论】:

【参考方案7】:

使用 UITextView 代替 UILabel,它具有将文本转换为超链接的属性

Swift 代码:

yourTextView.editable = false
yourTextView.dataDetectorTypes = UIDataDetectorTypes.All
//or
yourTextView.dataDetectorTypes = UIDataDetectorTypes.PhoneNumber
//or
yourTextView.dataDetectorTypes = UIDataDetectorTypes.Link

【讨论】:

关于如何在 UILabel 中使用的问题,而不是 TextViews。谢谢。【参考方案8】:
extension UITapGestureRecognizer 

    func didTapAttributedTextInLabel(label: UILabel, inRange targetRange: NSRange) -> Bool 

        let layoutManager = NSLayoutManager()
        let textContainer = NSTextContainer(size: CGSize.zero)
        let textStorage = NSTextStorage(attributedString: label.attributedText!)

        // Configure layoutManager and textStorage
        layoutManager.addTextContainer(textContainer)
        textStorage.addLayoutManager(layoutManager)

        // Configure textContainer
        textContainer.lineFragmentPadding = 0.0
        textContainer.lineBreakMode = label.lineBreakMode
        textContainer.maximumNumberOfLines = label.numberOfLines
        textContainer.size = label.bounds.size

        // main code
        let locationOfTouchInLabel = self.location(in: label)

        let indexOfCharacter = layoutManager.characterIndex(for: locationOfTouchInLabel, in: textContainer, fractionOfDistanceBetweenInsertionPoints: nil)
        let indexOfCharacterRange = NSRange(location: indexOfCharacter, length: 1)
        let indexOfCharacterRect = layoutManager.boundingRect(forGlyphRange: indexOfCharacterRange, in: textContainer)
        let deltaOffsetCharacter = indexOfCharacterRect.origin.x + indexOfCharacterRect.size.width

        if locationOfTouchInLabel.x > deltaOffsetCharacter 
            return false
         else 
            return NSLocationInRange(indexOfCharacter, targetRange)
        
    

【讨论】:

【参考方案9】:

为什么不直接使用 NSMutableAttributedString

let attributedString = NSMutableAttributedString(string: "Want to learn iOS? Just visit developer.apple.com!")
        attributedString.addAttribute(.link, value: "https://developer.apple.com", range: NSRange(location: 30, length: 50))

        myView.attributedText = attributedString

您可以找到更多详情here

【讨论】:

我今天刚尝试从 UILabel 拨打电话,上面的代码不起作用。我已将 dev.appl.com 替换为 tel://1234567。可能这个答案需要更新。【参考方案10】:

使用 UIButton 的 Swift 4.0 可能解决方案

     phoneButton = UIButton(frame: CGRect(x: view.frame.width * 0, y: view.frame.height * 0.1, width: view.frame.width * 1, height: view.frame.height * 0.05))
     phoneButton.setTitle("333-333-3333", for: .normal )
     phoneButton.setTitleColor(UIColor(red: 0 / 255, green: 0 / 255, blue: 238 / 255, alpha: 1.0), for: .normal)
     phoneButton.addTarget(self, action: #selector(self.callPhone), for: .touchUpInside )

     @objc func callPhone()

         UIApplication.shared.open(URL(string:"tel://3333333333")!, options: [:] , completionHandler: nil)


    

【讨论】:

以上是关于如何制作 URL/电话可点击的 UILabel?的主要内容,如果未能解决你的问题,请参考以下文章

iOS UITextView 或 UILabel 带有可点击的动作链接[重复]

如何使 UILabel 可点击?

如何使 UILabel 可点击?

如何手动制作macOS High Sierra可启动安装U盘

如何制作Windows10安装U盘

如何使整个区域可点击?