首页 > 解决方案 > 快速在文本字段/搜索栏中键入文本视图后,将其滚动到特定子字符串

问题描述

我正在尝试平滑滚动到 textView 中的特定子字符串,并将此子字符串放在可见 textview 区域的顶部,可以动画或不动画。我尝试了很多不同的解决方案,但我唯一可以使用的解决方案是以下一种:

func scrollToSubstring (substring:String) {
    let value = getFirstHighlightedWordPosition(word: substring)
    themeTextView.setContentOffset(CGPoint(x: 0.0, y: 0.5), animated: true) //first adjustment
    
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { [self] in
        self.setCursorPosition(value: value)
        self.ScrollToCursorPosition() //second adjustment
    }
}

func ScrollToCursorPosition() {
    //coordinates of cursor
    if let cursorPosition = self.themeTextView.selectedTextRange?.start
    {
        print(self.themeTextView.selectedRange)
        let rect: CGRect = self.themeTextView.caretRect(for: cursorPosition)
        let point = CGPoint(x: 0, y: rect.origin.y)
        //print("cursor position:",point)
        self.themeTextView.setContentOffset(point, animated: true)
    }
}

问题是它不平滑,因为它进行了 2 次调整,并且只能进行动画处理。我相信一定有更好的方法让它发挥作用。

我试图改进此代码但没有成功:

  1. 删除第一个调整会导致更长的文本视图出现一些问题

  2. 如果第一次调整的动画设置为 false,则不会滚动,但如果设置为 true,则可以将第二次调整的动画设置为 true 或 false(滚动时有/没有动画)。

  3. 删除 dispatchQueue 0.5:滚动无法正常工作,所以我想它需要一个时间延迟(编辑:我将 0.5 降低到 0.25,它更平滑并且似乎适用于大于 0.25 的值)

  4. 如果修改上面的代码,点给出不同的值:我猜 setCursorPosition 和 caretRect 之间存在问题

我从以下位置调用scrolltosubstring:

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    scrollToSubstring (substring: searchText)
}

有时在一场演出之后。

标签: swiftscrolltextviewsubstringsearchbar

解决方案


你应该对这个唯一的方法没问题:

func scrollToWord(word: String, animated: Bool = true, minCharacterLimit: Int = 3) {
    
    // Limit word lenght for search
    guard word.count >= minCharacterLimit else { return }
    
    // Getting needed ranges
    let range: NSRange = (yourTextView.text as NSString).range(of: word)
    let beginning: UITextPosition = yourTextView.beginningOfDocument
    
    guard let start: UITextPosition = yourTextView.position(from: beginning, offset: range.location),
          let end: UITextPosition = yourTextView.position(from: start, offset: range.length),
          let textRange: UITextRange = yourTextView.textRange(from: start, to: end) else { return }
    
    // Converting Range to Rect
    let rect: CGRect = yourTextView.firstRect(for: textRange)
    
    // Scrolling in text view
    self.yourTextView.setContentOffset(rect.origin, animated: animated)
}

推荐阅读