Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scroll UITextView to specific text

i have a uitextview with large texts and above i have a search field. Anything searched, i would love the uitextview to scroll to that specific text and hightlight. And i need to make sure that the uitextview scrolls in such a way that the searched text stays in the first line

I populated the textview with attributed text with some attributes. What i tried is get the text before the target text and tried to get the size of it adding the exact attributes i added on textview text at the beginning.

made a CGPoint using that height and set the contentOffset of the uitextview. But the textview scrolled no where near the target text. Maybe my approach is wrong as i dont have the width of the textview when setting attributes

My code is :

func goToBla() {
        if let string = ayatTextView.text {

            if let range = string.range(of: tazweedAyahas[8].text) {
                let firstPart = string[string.startIndex..<range.lowerBound]
                print("before \(tazweedAyahas[5].text) : ")
                print(firstPart)


                if let otherStr = firstPart as? NSString {
                    let paragraphStyle = NSMutableParagraphStyle()
                    paragraphStyle.alignment = .center

                    let size = otherStr.size(withAttributes: [NSAttributedStringKey.paragraphStyle: paragraphStyle,
                                                   NSAttributedStringKey.font: UIFont(name: "me_quran", size: 30)
                        ])

                    let point = CGPoint(x: 0, y: size.height)
                    ayatTextView.setContentOffset(point, animated: true)
                }


            }
        }


    }
like image 814
Ahsan Aasim Avatar asked May 05 '18 15:05

Ahsan Aasim


1 Answers

Your approach is much more complicated than it needs to be. Use the scrollRangeToVisible method of UITextView.

func goToBla() {
    if let string = ayatTextView.text, let range = string.localizedStandardRange(of: tazweedAyahas[8].text) {
        let viewRange = NSRange(range, in: string)
        ayatTextView.selectedRange = viewRange // optional
        ayatTextView.scrollRangeToVisible(viewRange)
    }
}

Note the following:

  1. Use localizedStandardRange when searching if you want to ignore diacritics and case, and you want other locale specific search features.
  2. Call selectedRange if you want the matching text selected.

If you want to get the selected range at the top, try something like this instead of calling scrollRangeToVisible:

let rect = ayatTextView.layoutManager.boundingRect(forGlyphRange: viewRange, in: ayatTextView.textContainer)
ayatTextView.contentOffset = CGPoint(x: 0, y: rect.origin.y)
like image 118
rmaddy Avatar answered Oct 13 '22 20:10

rmaddy