如何制作 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.h
、FRHyperLabel.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 带有可点击的动作链接[重复]