Réponses:
Vous pouvez utiliser UITextView
et sélectionner Détection des liens, numéros de téléphone et autres éléments dans l'inspecteur.
Utilisez à la UITextView
place de UILabel
et il a une propriété pour convertir votre texte en lien hypertexte.
yourTextView.editable = NO;
yourTextView.dataDetectorTypes = UIDataDetectorTypeAll;
yourTextView.editable = false;
yourTextView.dataDetectorTypes = UIDataDetectorTypes.All;
Cela détectera automatiquement les liens.
Consultez la documentation pour plus de détails.
https://github.com/mattt/TTTAttributedLabel
C'est certainement ce dont vous avez besoin. Vous pouvez également appliquer des attributs à votre étiquette, comme le soulignement, et lui appliquer différentes couleurs. Vérifiez simplement les instructions pour les URL cliquables.
Principalement, vous faites quelque chose comme ce qui suit:
NSRange range = [label.text rangeOfString:@"me"];
[label addLinkToURL:[NSURL URLWithString:@"http://github.com/mattt/"] withRange:range]; // Embedding a custom link in a substring
Vous pouvez créer un UIButton et un setText personnalisés comme vous le souhaitez et ajouter une méthode avec cela.
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
}
Si vous voulez que cela soit géré par UILabel et non par UITextView, vous pouvez créer une sous-classe UILabel, comme celle-ci:
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)!)
}
}
})
}}
Cette classe a été créée en réutilisant le code de cette réponse . Afin de créer des chaînes attribuées, consultez cette réponse . Et ici, vous pouvez trouver comment créer des URL de téléphone.
Utilisez ceci que j'ai tellement aimé car crée un lien avec une couleur bleue vers un texte particulier uniquement pas sur le texte entier de l'étiquette: FRHyperLabel
Faire:
Téléchargez le lien ci-dessus et copiez FRHyperLabel.h
-le FRHyperLabel.m
dans votre projet.
Glissez-déposez UILabel
dans votre Storyboard
et définissez le nom de classe personnalisé pour FRHyperLabel
identifier l'inspecteur comme indiqué dans l'image.
@property (weak, nonatomic) IBOutlet FRHyperLabel *label;
`NSString * string = @" En téléchargeant, j'accepte les conditions d'utilisation "; NSDictionary * attributes = @ {NSFontAttributeName: [UIFont preferFontForTextStyle: 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"]];
}];`
Utilisez UITextView au lieu de UILabel et il a une propriété pour convertir votre texte en lien hypertexte
Code rapide:
yourTextView.editable = false
yourTextView.dataDetectorTypes = UIDataDetectorTypes.All
//or
yourTextView.dataDetectorTypes = UIDataDetectorTypes.PhoneNumber
//or
yourTextView.dataDetectorTypes = UIDataDetectorTypes.Link
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)
}
}
}
Pourquoi ne pas simplement utiliser 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
Vous pouvez trouver plus de détails ici
Swift 4.2, version Xcode 9.3
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(self.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;
}
}
}
@objc 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(NSAttributedStringKey.link, 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)!)
}
}
})
}}
Solution possible Swift 4.0 avec UIButton
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)
}