简体   繁体   中英

Fix cursor size for modified paragraph spacing in UITextView

I have a custom, editable UITextView and I modified the paragraph spacing like so:

func layoutManager(_ layoutManager: NSLayoutManager, paragraphSpacingBeforeGlyphAt glyphIndex: Int, withProposedLineFragmentRect rect: CGRect) -> CGFloat {
    return 10
}

func layoutManager(_ layoutManager: NSLayoutManager, paragraphSpacingAfterGlyphAt glyphIndex: Int, withProposedLineFragmentRect rect: CGRect) -> CGFloat {
    return 10
}

This causes the cursor being very big. I've tried to fix that by overriding the caretRect :

override func caretRect(for position: UITextPosition) -> CGRect {
    let defaulCaretRect = super.caretRect(for: position)
    return CGRect(x: defaulCaretRect.origin.x, y: defaulCaretRect.origin.y, width: defaulCaretRect.width, height: 22)
}

It works perfectly in some cases, but in other cases, the origin.y is wrong:

错误的来源.y

If I ajdust the origin.y , it breaks it in cases where it was correct. I don't know how to recognize if the origin.y needs to be fixed or not. Am I missing something?

I've seen here on SO some older answers using the following:

rect.size.height = font.pointSize - font.descender

But fore some reason, this had no effect. Any ideas?

Lastly, the bigger paragraph spacing is also causing too big selection handles:

在此处输入图像描述

Any way of resolving that as well?

I think I've figured it out. Adjusting the caret height with font, as suggested in other questions found on SO, seems to work great. What was missing was fixing the caret's origin Y.

I thought there must be a reason why Apple gives us the UITextPosition . Using it, I was able to get the line text and paragraph text. Having these, I can check if the caret is on the first line of the paragraph, which was causing the problems.

override func caretRect(for position: UITextPosition) -> CGRect {
    var superRect = super.caretRect(for: position)
    
    guard let paragraphRange = tokenizer.rangeEnclosingPosition(position, with: .paragraph, inDirection: .storage(.backward)),
          let paragraphText = text(in: paragraphRange)else { return superRect }
    
    guard let lineRange = tokenizer.rangeEnclosingPosition(position, with: .line, inDirection: .storage(.backward)),
          let lineText = text(in: lineRange) else { return superRect }
    
    guard let font = font else { return superRect }
    
     if paragraphText.hasPrefix(lineText) {
        superRect.origin.y += 10
    }
    
    superRect.size.height = font.pointSize - font.descender
    
    return superRect
}

I have no idea how to fix the big selection handles, though.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM