Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //
- // TapableLabel.swift
- // AspirinUIKit
- //
- // Created by HamGuy on 2018/11/21.
- //
- import UIKit
- public protocol TapableLabelDelegate: NSObjectProtocol {
- func tapableLabel(_ label: TapableLabel, didTapUrl url: String, atRange range: NSRange)
- }
- public class TapableLabel: UILabel {
- private var links: [String: NSRange] = [:]
- private(set) var layoutManager = NSLayoutManager()
- private(set) var textContainer = NSTextContainer(size: CGSize.zero)
- private(set) var textStorage = NSTextStorage() {
- didSet {
- textStorage.addLayoutManager(layoutManager)
- }
- }
- public weak var delegate: TapableLabelDelegate?
- public override var attributedText: NSAttributedString? {
- didSet {
- if let attributedText = attributedText {
- textStorage = NSTextStorage(attributedString: attributedText)
- } else {
- textStorage = NSTextStorage()
- links = [:]
- }
- }
- }
- public override var lineBreakMode: NSLineBreakMode {
- didSet {
- textContainer.lineBreakMode = lineBreakMode
- }
- }
- public override var numberOfLines: Int {
- didSet {
- textContainer.maximumNumberOfLines = numberOfLines
- }
- }
- public override init(frame: CGRect) {
- super.init(frame: frame)
- setup()
- }
- public required init?(coder aDecoder: NSCoder) {
- super.init(coder: aDecoder)
- setup()
- }
- public override func layoutSubviews() {
- super.layoutSubviews()
- textContainer.size = bounds.size
- }
- /// addLinks
- ///
- /// - Parameters:
- /// - text: text of link
- /// - url: link url string
- public func addLink(_ text: String, withURL url: String) {
- guard let theText = attributedText?.string as? NSString else {
- return
- }
- let range = theText.range(of: text)
- guard range.location != NSNotFound else {
- return
- }
- links[url] = range
- }
- private func setup() {
- isUserInteractionEnabled = true
- layoutManager.addTextContainer(textContainer)
- textContainer.lineFragmentPadding = 0
- textContainer.lineBreakMode = lineBreakMode
- textContainer.maximumNumberOfLines = numberOfLines
- }
- public override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
- guard let locationOfTouch = touches.first?.location(in: self) else {
- return
- }
- textContainer.size = bounds.size
- let indexOfCharacter = layoutManager.glyphIndex(for: locationOfTouch, in: textContainer)
- for (urlString, range) in links {
- if NSLocationInRange(indexOfCharacter, range), let url = URL(string: urlString) {
- delegate?.tapableLabel(self, didTapUrl: urlString, atRange: range)
- }
- }
- }
- }
Add Comment
Please, Sign In to add comment