Advertisement
Guest User

Untitled

a guest
Sep 20th, 2019
96
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.07 KB | None | 0 0
  1. import UIKit
  2.  
  3. class LabelTappable: UILabel {
  4.  
  5. let layoutManager = NSLayoutManager()
  6. let textContainer = NSTextContainer(size: CGSize.zero)
  7. let tapGesture = UITapGestureRecognizer()
  8.  
  9. var textStorage = NSTextStorage() {
  10. didSet {
  11. textStorage.addLayoutManager(layoutManager)
  12. }
  13. }
  14.  
  15. var didTap: ((_ label: UILabel, _ characterIndex: Int) -> Void)?
  16.  
  17. override var attributedText: NSAttributedString? {
  18. didSet {
  19. if let attributedText = attributedText {
  20. textStorage = NSTextStorage(attributedString: attributedText)
  21. } else {
  22. textStorage = NSTextStorage()
  23. }
  24. }
  25. }
  26. override var lineBreakMode: NSLineBreakMode {
  27. didSet {
  28. textContainer.lineBreakMode = lineBreakMode
  29. }
  30. }
  31.  
  32. override var numberOfLines: Int {
  33. didSet {
  34. textContainer.maximumNumberOfLines = numberOfLines
  35. }
  36. }
  37.  
  38. required init?(coder aDecoder: NSCoder) {
  39. super.init(coder: aDecoder)
  40. setUp()
  41. }
  42.  
  43. override init(frame: CGRect) {
  44. super.init(frame: frame)
  45. setUp()
  46. }
  47.  
  48. func setUp() {
  49. isUserInteractionEnabled = true
  50. layoutManager.addTextContainer(textContainer)
  51. textContainer.lineFragmentPadding = 0
  52. textContainer.lineBreakMode = lineBreakMode
  53. textContainer.maximumNumberOfLines = numberOfLines
  54. tapGesture.addTarget(self, action: #selector(LabelTappable.labelTapped(_:)))
  55. addGestureRecognizer(tapGesture)
  56. }
  57.  
  58. override func layoutSubviews() {
  59. super.layoutSubviews()
  60. textContainer.size = bounds.size
  61. }
  62.  
  63. @objc func labelTapped(_ gesture: UITapGestureRecognizer) {
  64. guard gesture.state == .ended else {
  65. return
  66. }
  67. let locationOfTouch = gesture.location(in: gesture.view)
  68. let textBoundingBox = layoutManager.usedRect(for: textContainer)
  69. let textContainerOffset = CGPoint(
  70. x: (bounds.width - textBoundingBox.width) / 2 - textBoundingBox.minX,
  71. y: (bounds.height - textBoundingBox.height) / 2 - textBoundingBox.minY
  72. )
  73. let locationOfTouchInTextContainer = CGPoint(
  74. x: locationOfTouch.x - textContainerOffset.x,
  75. y: locationOfTouch.y - textContainerOffset.y
  76. )
  77. let characterIndex = layoutManager.characterIndex(for: locationOfTouchInTextContainer,
  78. in: textContainer, fractionOfDistanceBetweenInsertionPoints: nil)
  79.  
  80. /* HOW TO USE */
  81. /*
  82. es for links
  83. self.didTap = { [weak self] label, characterIndex in
  84. guard let _ = self else {
  85. return
  86. }
  87.  
  88. if let url = label.attributedText?.attribute(.link, at: characterIndex, effectiveRange: nil) as? URL, UIApplication.shared.canOpenURL(url) {
  89. UIApplication.shared.open(url, options: [:], completionHandler: nil)
  90. }
  91. }
  92. */
  93.  
  94. didTap?(self, characterIndex)
  95. }
  96.  
  97. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement