Created
November 26, 2019 19:57
-
-
Save arpitdsoni/24c4b683902e1241345b9cf4c5ff4781 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
class HyperlinkLabel: UILabel { | |
var stringAndUrl: [String: URL] = [:] { | |
didSet { | |
attributedText = attributedText() | |
} | |
} | |
override init(frame: CGRect) { | |
super.init(frame: frame) | |
commonInit() | |
} | |
required init?(coder: NSCoder) { | |
super.init(coder: coder) | |
} | |
override func awakeFromNib() { | |
super.awakeFromNib() | |
commonInit() | |
} | |
func commonInit() { | |
numberOfLines = 0 | |
isUserInteractionEnabled = true | |
let tap = UITapGestureRecognizer(target: self, action: #selector(linkTapped(gesture:))) | |
addGestureRecognizer(tap) | |
} | |
} | |
fileprivate extension HyperlinkLabel { | |
@objc func linkTapped(gesture: UITapGestureRecognizer) { | |
guard let text = self.text as NSString? else { | |
return | |
} | |
for (string, url) in stringAndUrl { | |
let range = text.localizedStandardRange(of: string) | |
let tapLocation = gesture.location(in: self) | |
let index = self.indexOfAttributedTextCharacterAtPoint(point: tapLocation) | |
if checkRange(range, containsIndex: index) { | |
SafariManager.show(url) | |
return | |
} | |
} | |
} | |
func attributedText() -> NSAttributedString { | |
guard let text = self.text else { | |
return NSAttributedString(string: "") | |
} | |
let paragraphStyle = NSMutableParagraphStyle() | |
paragraphStyle.alignment = textAlignment | |
let attributedString = | |
NSMutableAttributedString(string: text, attributes: [ | |
.paragraphStyle: paragraphStyle, | |
.font: self.font as Any | |
]) | |
let boldFontAttribute = [ | |
NSAttributedString.Key.font: self.font.bold(), | |
NSAttributedString.Key.foregroundColor: UIColor.tintColor | |
] | |
for str in stringAndUrl.keys { | |
attributedString.addAttributes(boldFontAttribute, range: (text as NSString).range(of: str)) | |
} | |
return attributedString | |
} | |
func indexOfAttributedTextCharacterAtPoint(point: CGPoint) -> Int { | |
guard let attributedText = attributedText else { | |
preconditionFailure("This method is developed for attributed string") | |
} | |
let textStorage = NSTextStorage(attributedString: attributedText) | |
let layoutManager = NSLayoutManager() | |
textStorage.addLayoutManager(layoutManager) | |
let textContainer = NSTextContainer(size: self.frame.size) | |
textContainer.lineFragmentPadding = 0 | |
textContainer.maximumNumberOfLines = self.numberOfLines | |
textContainer.lineBreakMode = self.lineBreakMode | |
layoutManager.addTextContainer(textContainer) | |
let index = layoutManager.characterIndex(for: point, in: textContainer, fractionOfDistanceBetweenInsertionPoints: nil) | |
return index | |
} | |
func checkRange(_ range: NSRange, containsIndex index: Int) -> Bool { | |
return index > range.location && index < range.location + range.length | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment