I need to add some tapGestures to some part of a text, thats in a UILabel. It seems to be able to make a hyperlink - so I guess its possible to make a functioncall as well, but I'm just not sure how to do it.
Heres my code:
let regularFont = UIFont(name: Constants.robotoRegular, size: 13)!
let att1 = [NSFontAttributeName: regularFont]
let turqoiseFont = UIFont(name: Constants.robotoBold, size: 13)!
let att2 = [NSFontAttributeName: turqoiseFont]
let attString1 = NSMutableAttributedString(string: "By creating a profile, I accept ", attributes: att1)
attString1.addAttribute(NSForegroundColorAttributeName, value: UIColor.darkGrayColor(), range: NSMakeRange(0, attString1.length))
let attString2 = NSMutableAttributedString(string: "Terms and Conditions ", attributes: att2)
attString2.addAttribute(NSForegroundColorAttributeName, value: Colors.loginButtonColor, range: NSMakeRange(0, attString2.length))
let attString3 = NSMutableAttributedString(string: "and ", attributes: att1)
attString3.addAttribute(NSForegroundColorAttributeName, value: UIColor.darkGrayColor(), range: NSMakeRange(0, attString3.length))
let attString4 = NSMutableAttributedString(string: "Private Policy.", attributes: att2)
attString4.addAttribute(NSForegroundColorAttributeName, value: Colors.loginButtonColor, range: NSMakeRange(0, attString4.length))
let index = "\(attString1.string.endIndex)"
attString1.insertAttributedString(attString4, atIndex: Int(index)!)
attString1.insertAttributedString(attString3, atIndex: Int(index)!)
attString1.insertAttributedString(attString2, atIndex: Int(index)!)
termsAndConditionLabel.attributedText = attString1
I want the turqoise parts to be able to take the user to either Terms and Conditions, or Private Policy. Can anyone please help me with this problem? :))
I once made the same thing, but used textView instead of UILabel, you should create your own attributes, and add them to attributed string, and then handle tap, here some code
your code with my modifications
let regularFont = UIFont(name: "HelveticaNeue", size: 13)!
let att1 = [NSFontAttributeName: regularFont]
let turqoiseFont = UIFont(name: "HelveticaNeue", size: 13)!
let att2 = [NSFontAttributeName: turqoiseFont]
let mattString : NSMutableAttributedString = NSMutableAttributedString()
let attString1 = NSMutableAttributedString(string: "By creating a profile, I accept ", attributes: att1)
attString1.addAttribute(NSForegroundColorAttributeName, value: UIColor.darkGray, range: NSMakeRange(0, attString1.length))
let attString2 = NSMutableAttributedString(string: "Terms and Conditions ", attributes: att2)
attString2.addAttribute(NSForegroundColorAttributeName, value: UIColor.red, range: NSMakeRange(0, attString2.length))
let attString3 = NSMutableAttributedString(string: "and ", attributes: att1)
attString3.addAttribute(NSForegroundColorAttributeName, value: UIColor.darkGray, range: NSMakeRange(0, attString3.length))
let attString4 = NSMutableAttributedString(string: "Private Policy.", attributes: att2)
attString4.addAttribute(NSForegroundColorAttributeName, value: UIColor.red, range: NSMakeRange(0, attString4.length))
mattString.append(attString1)
mattString.append(attString2)
mattString.append(attString3)
mattString.append(attString4)
let attributes = ["link" : "termsLink"]
let attributes2 = ["link" : "policyLink"]
let str : NSString = mattString.string as NSString
mattString.addAttributes(attributes, range: str.range(of: "Terms and Conditions"))
mattString.addAttributes(attributes2, range: str.range(of: "Private Policy"))
_textView.attributedText = mattString
_textView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.singleTap(tap:))))
and func to handle tap
func singleTap(tap : UITapGestureRecognizer) {
let layoutManager = _textView.layoutManager
let location = tap.location(in: _textView)
let index = layoutManager.characterIndex(for: location, in: _textView.textContainer, fractionOfDistanceBetweenInsertionPoints: nil)
if index > _textView.textStorage.length {return}
var range : NSRange = NSRange()
if let type = _textView.attributedText.attribute("link", at: index, effectiveRange: &range) as? String {
if type == "termsLink" {
//.. do smth
} else {
//.. do smth
}
}
}
UPDATE:
here is the class I wrote to use Label
https://github.com/barbados88/TapableLabel/blob/master/TapableLabel.swift
I have changed Alexandr Kolesnik his answer for UILabel
with Swift 4. If someone want to use with UILabel
too
let regularFontAttribute = [NSAttributedStringKey.font: UIFont(name: "Lato-Regular", size: 15.0)!]
let boldFontAttribute = [NSAttributedStringKey.font: UIFont(name: "Lato-Bold", size: 15.0)!]
let mattString : NSMutableAttributedString = NSMutableAttributedString()
let attString1 = NSMutableAttributedString(string: "By creating a profile, I accept ", attributes: regularFontAttribute)
let anotherAttribute1 = [NSAttributedStringKey.foregroundColor: UIColor.black]
attString1.addAttributes(anotherAttribute1, range: NSMakeRange(0, attString1.length))
let attString2 = NSMutableAttributedString(string: "Terms and Conditions ", attributes: boldFontAttribute)
let anotherAttribute2 = [NSAttributedStringKey.foregroundColor: UIColor.red]
attString2.addAttributes(anotherAttribute2, range: NSMakeRange(0, attString2.length))
let attString3 = NSMutableAttributedString(string: "and ", attributes: regularFontAttribute)
let anotherAttribute3 = [NSAttributedStringKey.foregroundColor: UIColor.black]
attString3.addAttributes(anotherAttribute3, range: NSMakeRange(0, attString3.length))
let attString4 = NSMutableAttributedString(string: "Private Policy.", attributes: boldFontAttribute)
let anotherAttribute4 = [NSAttributedStringKey.foregroundColor: UIColor.red]
attString4.addAttributes(anotherAttribute4, range: NSMakeRange(0, attString4.length))
mattString.append(attString1)
mattString.append(attString2)
mattString.append(attString3)
mattString.append(attString4)
let attributes: [NSAttributedStringKey : Any] = [NSAttributedStringKey(rawValue: "link") : "termsLink"]
let attributes2: [NSAttributedStringKey : Any] = [NSAttributedStringKey(rawValue: "link") : "policyLink"]
let str : NSString = mattString.string as NSString
mattString.addAttributes(attributes, range: str.range(of: "Terms and Conditions"))
mattString.addAttributes(attributes2, range: str.range(of: "Private Policy"))
self.attributedLabel.attributedText = mattString
self.attributedLabel.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.singleTap(_:))))
self.attributedLabel.isUserInteractionEnabled = true
and func to handle tap and detect tapped text
@objc func singleTap(_ tap : UITapGestureRecognizer) {
let attributedText = NSMutableAttributedString(attributedString: self.attributedLabel!.attributedText!)
attributedText.addAttributes([NSAttributedStringKey.font: self.attributedLabel!.font], range: NSMakeRange(0, (self.attributedLabel!.attributedText?.string.count)!))
// Create instances of NSLayoutManager, NSTextContainer and NSTextStorage
let layoutManager = NSLayoutManager()
let textContainer = NSTextContainer(size: CGSize(width: (self.attributedLabel?.frame.width)!, height: (self.attributedLabel?.frame.height)!+100))
let textStorage = NSTextStorage(attributedString: attributedText)
// Configure layoutManager and textStorage
layoutManager.addTextContainer(textContainer)
textStorage.addLayoutManager(layoutManager)
// Configure textContainer
textContainer.lineFragmentPadding = 0.0
textContainer.lineBreakMode = self.attributedLabel!.lineBreakMode
textContainer.maximumNumberOfLines = self.attributedLabel!.numberOfLines
let labelSize = self.attributedLabel!.bounds.size
textContainer.size = labelSize
let tapLocation = tap.location(in: self.attributedLabel)
// get the index of character where user tapped
let index = layoutManager.characterIndex(for: tapLocation, in: textContainer, fractionOfDistanceBetweenInsertionPoints: nil)
if index > (self.attributedLabel.text?.count)! { return }
var range : NSRange = NSRange()
if let type = self.attributedLabel.attributedText?.attribute(NSAttributedStringKey(rawValue: "link"), at: index, effectiveRange: &range) as? String {
// to get full text which was clicked
print((self.attributedLabel.text! as NSString).substring(with: range))
if type == "termsLink" {
//.. do smth
print("termsLink click")
} else { //policyLink
//.. do smth
print("policyLink click")
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With