7

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)
                }


            }
        }


    }
Ahsan Aasim
  • 1,177
  • 3
  • 14
  • 40

1 Answers1

10

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)
rmaddy
  • 314,917
  • 42
  • 532
  • 579
  • this approach works nicely. There is only one problem i am facing with it. uitextview scrolls and show the searched text and thats great. But i need to make sure that the uitextview scrolls in such a way that the searched text stays in the first line – Ahsan Aasim May 06 '18 at 05:03
  • 2
    It would have been helpful if that important detail was in your question. – rmaddy May 06 '18 at 05:06