i need to locate my character location in my UILabel (it has ParagraphLineSpacing and AttributedText with multiline),
i have got my character's index, but now i can't get X and Y coordinate from my index.
i Have found this http://techqa.info/programming/question/19417776/how-do-i-locate-the-cgrect-for-a-substring-of-text-in-a-uilabel
and i translated to my Swift 3.1 code
func boundingRect(forCharacterRange range: NSRange) -> CGRect {
let textStorage = NSTextStorage(attributedString: self.attributedText!)
let layoutManager = NSLayoutManager()
textStorage.addLayoutManager(layoutManager)
let textContainer = NSTextContainer(size: bounds.size)
textContainer.lineFragmentPadding = 0
layoutManager.addTextContainer(textContainer)
var glyphRange: NSRange
// Convert the range for glyphs.
layoutManager.characterRange(forGlyphRange: range, actualGlyphRange: glyphRange)
return layoutManager.boundingRect(forGlyphRange: glyphRange, in: textContainer)
}
but, unfortunately, i can't really use this code because actualGlyphRange ask NSRangePointer, not NSRange, so i changed my translated code to
func boundingRect(forCharacterRange range: NSRange) -> CGRect {
let textStorage = NSTextStorage(attributedString: self.attributedText!)
let layoutManager = NSLayoutManager()
textStorage.addLayoutManager(layoutManager)
let textContainer = NSTextContainer(size: bounds.size)
textContainer.lineFragmentPadding = 0
layoutManager.addTextContainer(textContainer)
//var glyphRange: NSRange
let a = MemoryLayout<NSRange>.size
let pointer:NSRangePointer = NSRangePointer.allocate(capacity: a)
layoutManager.characterRange(forGlyphRange: range, actualGlyphRange: pointer)
return layoutManager.boundingRect(forGlyphRange: range, in: textContainer)
}
i don't understand what
var glyphRange: NSrange
usage, so i removed it and now the code is working, but the result is 60% not accurate especially when my character located on the second line or the third line. Do i messed up the translation here? Or are there any better method to get my character coordinate accurately?
i use
NSMakeRange(index, 1)
for my params to locate one specific character
=======UPDATED=======
I have tried custom UITextView to access its layout Manager, but unfortunately, the position is still inaccurate if there are 2 lines or more. (only accurate if there is only 1 line in my textView)
class LyricTextView: UITextView {
func boundingRect(forCharacterRange range: NSRange) -> CGRect {
let inset = self.textContainerInset
let rect = self.layoutManager.boundingRect(forGlyphRange: range, in: textContainer).offsetBy(dx: inset.left, dy: inset.top)
return rect
}
}
Am i missing something in this new code? It is getting nearly done