Получить текущий индекс абзаца - PullRequest
0 голосов
/ 26 июня 2019

Я хочу найти текущий абзац, в котором печатает пользователь (где находится курсор). Пример: Здесь это будет во втором абзаце.

image

Я знаю, что могу разделять абзацы, используя: let components = textView.text.components(separatedBy: "\n"), но я не уверен, как бы я проверил проверку текущего абзаца редактирования. Есть идеи?

1 Ответ

0 голосов
/ 26 июня 2019

Вот один подход ...

Получить Y-позицию каретки (точки вставки).Затем выполните цикл по перечислению абзацев в textView, сравнивая их ограничивающие фрагменты с позицией каретки:

extension UITextView {

    func boundingFrame(ofTextRange range: Range<String.Index>?) -> CGRect? {

        guard let range = range else { return nil }
        let length = range.upperBound.encodedOffset-range.lowerBound.encodedOffset
        guard
            let start = position(from: beginningOfDocument, offset: range.lowerBound.encodedOffset),
            let end = position(from: start, offset: length),
            let txtRange = textRange(from: start, to: end)
            else { return nil }

        return selectionRects(for: txtRange).reduce(CGRect.null) { $0.union($1.rect) }

    }

}

// return value will be Zero-based index of the paragraphs
// if the textView has no text, return -1
@objc func getParagraphIndex(in textView: UITextView) -> Int {

    // this will make sure the the text container has updated
    theTextView.layoutManager.ensureLayout(for: theTextView.textContainer)

    // make sure we have some text
    guard let str = theTextView.text else { return -1 }

    // get the full range
    let textRange = str.startIndex..<str.endIndex

    // we want to enumerate by paragraphs
    let opts:NSString.EnumerationOptions = .byParagraphs

    var caretYPos = CGFloat(0)
    if let selectedTextRange = theTextView.selectedTextRange {
        caretYPos = theTextView.caretRect(for: selectedTextRange.start).origin.y + 4
    }

    var pIndex = -1
    var i = 0

    // loop through the paragraphs, comparing the caret Y position to the paragraph bounding rects
    str.enumerateSubstrings(in: textRange, options: opts) {
        (substring, substringRange, enclosingRange, b) in

        // get the bounding rect for the sub-rects in each paragraph
        if let boundRect = self.theTextView.boundingFrame(ofTextRange: substringRange) {

            if caretYPos > boundRect.origin.y && caretYPos < boundRect.origin.y + boundRect.size.height {
                pIndex = i
                b = true
            }

            i += 1
        }
    }

    return pIndex
}

Использование:

let paraIndex = getParagraphIndex(in myTextView)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...