Last active
October 30, 2024 21:26
-
-
Save leoiphonedev/2d00d7de485b8f261e010fff333cba0f to your computer and use it in GitHub Desktop.
Extension for UITapGesture that contains a function to detect range of particular text in UILabel's text.
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
extension UITapGestureRecognizer { | |
func didTapAttributedTextInLabel(label: UILabel, inRange targetRange: NSRange) -> Bool { | |
// Create instances of NSLayoutManager, NSTextContainer and NSTextStorage | |
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 | |
let labelSize = label.bounds.size | |
textContainer.size = labelSize | |
// Find the tapped character location and compare it to the specified range | |
let locationOfTouchInLabel = self.location(in: label) | |
let textBoundingBox = layoutManager.usedRect(for: 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); | |
var indexOfCharacter = layoutManager.characterIndex(for: locationOfTouchInTextContainer, in: textContainer, fractionOfDistanceBetweenInsertionPoints: nil) | |
indexOfCharacter = indexOfCharacter + 4 | |
return NSLocationInRange(indexOfCharacter, targetRange) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@geek-Shayan Thanks for the simplified code.
I am still facing some issue problem where the characterIndex is calculated incorrectly as the Number of lines increases.
I found UILabel's attributed text's default size is slightly larger than UITextView's Attributed Text (which uses layoutManager and textStorage inside it).
For now the working solution is giving the entire attributed string constant font size or scaledValue
attributes: [.font: UIFont.systemFont(ofSize: UIFontMetrics.default.scaledValue(for: xSize))]
Tag me if anyone found proper solution