HomeiOS Developmentios - The best way to set a uiview's bounds to the...

ios – The best way to set a uiview’s bounds to the identical measurement as NSTextLayoutFragment.layoutFragmentFrame


I’m attempting to develop my very own UIView that leverages TextKit2 to take management over the textual content rendering to use customized drawing.

The issue I’m dealing with thus far is that the UIView is at all times greater than the precise bounds that the textual content wants.

I do know that you need to use layoutFragmentFrame or renderingSurfaceBounds inside a subclass of NSTextLayoutFragment to get the precise bounds for the textual content – however I used to be not ready resize the view accordingly.

This screenshot illustrates the issue:

problem

My UIView implementation seems to be like this:

import UIKit
remaining class TextKit2UIView: UIView, NSTextLayoutManagerDelegate {
    let contentStorage = NSTextContentStorage()
    let layoutManager = NSTextLayoutManager()
    let textContainer = NSTextContainer(measurement: .zero)

    override init(body: CGRect) {
        tremendous.init(body: body)
        
        contentStorage.addTextLayoutManager(layoutManager)
        layoutManager.textContainer = textContainer
        layoutManager.delegate = self
        backgroundColor = .brown.withAlphaComponent(0.2)
        textContainer.lineFragmentPadding = 0
        textContainer.lineBreakMode = .byTruncatingTail
        
        contentStorage.attributedString = NSAttributedString(
            string: "Integer bibendum luctus metus, vel mattis diam consequat non. Phasellus magna augue, faucibus et ullamcorper sit amet, vehicula quis nunc. Phasellus nisl arcu, tempus id metus ac, tempus mollis nisi. Duis in ultrices lectus.",
            attributes: [.font: UIFont.systemFont(ofSize: 18)]
        )
    }

    required init?(coder: NSCoder) { nil }

    // utilizing my very own customized NSTextLayoutFragment
    func textLayoutManager(_ textLayoutManager: NSTextLayoutManager,
                           textLayoutFragmentFor location: NSTextLocation,
                           in textElement: NSTextElement) -> NSTextLayoutFragment {
        CustomLayoutFragment(textElement: textElement, vary: textElement.elementRange)
    }

    override func layoutSubviews() {
        tremendous.layoutSubviews()
        textContainer.measurement = bounds.measurement
        layoutManager.ensureLayout(for: contentStorage.documentRange)
        setNeedsDisplay()
    }

    override func draw(_ rect: CGRect) {
        guard let ctx = UIGraphicsGetCurrentContext() else { return }
        layoutManager.enumerateTextLayoutFragments(from: nil, choices: []) { fragment in
            fragment.draw(at: fragment.layoutFragmentFrame.origin, in: ctx)
            return true
        }
    }
    
}

And my NSTextLayoutFragment subclass seems to be like this (for now it simply renders the inexperienced rectangle behind the textual content, however it would have far more customized drawing in a while):

class CustomLayoutFragment: NSTextLayoutFragment {
    
    override func draw(at renderingOrigin: CGPoint, in ctx: CGContext) {
        let completeRect = self.layoutFragmentFrame
        let shapeRect = Rectangle().path(in: completeRect).cgPath
        ctx.saveGState()
        ctx.addPath(shapeRect)
        ctx.setFillColor(UIColor.inexperienced.withAlphaComponent(0.2).cgColor)
        ctx.fillPath()
        ctx.restoreGState()
        tremendous.draw(at: renderingOrigin, in: ctx)
    }
    
}

May somebody please clarify the way to obtain the specified habits? Particularly, how can I be certain that the uiView’s body matches the textual content’s body, eliminating the seen brown background that the screenshot reveals?

Please observe that I used SwiftUI to indicate the UIView on display and that I explicitly set the width and top of that view to some particular values to showcase the issue. The uiView (and due to this fact the brown rectangle) has the width and top supplied by the SwiftUI’s body modifier.

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisment -
Google search engine

Most Popular

Recent Comments