1

I've been playing around with attributed text in a UITextView (Swift 4.2 and noticed that once I introduced "paragraphSpacingBefore" into my design, the Caret becmae too large on the first line of each new paragraph.

I found this suggested fix on Stackoverflow which seemed to work ok to fix the caret size. The problem I found was the caret itself floats above the target line when that line was the start of a new paragraph.

UITextView lineSpacing make cursor height not same

Caret Floats above the target line

I tried solving it, maintaining the core idea of the original solution and adding some offset logic. During debugging I noticed that the original answer for caret size always adjusts the size even when not required so I added a variance filter (only adjust if variance > 10%). Did this because I think adjusting every time will interfere with my soln. to the floating caret problem.

If someone can take a look at my proposed approach, suggest improvements or a better way etc i'd be grateful:

override func caretRect(for position: UITextPosition) -> CGRect {
    var superRect = super.caretRect(for: position)
    guard let isFont = self.font else {
        return superRect
    }
    let proposedHeight: CGFloat = isFont.pointSize - isFont.descender
    var delta: CGFloat = superRect.size.height - proposedHeight
    delta = (delta * delta).squareRoot()

    //If the delta is < 10% of the original height just return the original rect
    if delta / superRect.size.height < 0.1 {
        return superRect
    }

    superRect.size.height = isFont.pointSize - isFont.descender
    // "descender" is expressed as a negative value,
    // so to add its height you must subtract its value
    superRect.origin.y = superRect.origin.y + delta
    // delta is used to correct for resized caret floating above the target line

    return superRect
}
roktecha
  • 71
  • 5

1 Answers1

0

I got a solution:

// Fix long cursor height when at the end of paragraph with paragraphspacing and wrong cursor position in titles with paragraph spacing before
override public func caretRect(for position: UITextPosition) -> CGRect {
    var superRect = super.caretRect(for: position)
    guard let isFont = self.font else { return superRect }

    let location = self.offset(from: self.beginningOfDocument, to: position)
    if let paragrahStyle = self.storage.attribute(.paragraphStyle, at: location, effectiveRange: nil) as? NSParagraphStyle {
        superRect.origin.y += paragrahStyle.paragraphSpacingBefore
    }

    superRect.size.height = isFont.pointSize - isFont.descender
    return superRect
}

The real problem paragraphSpacingBefore. So all you have to do is to get the paragraph styling attributes, get the spacing and move the cursor by that spacing. This works well with all the text.

Eduard
  • 176
  • 2
  • 10