Search code examples
iosswiftlabeluilabel

How can I calculate the last line width of label?


private func getLasLineWidth() -> CGFloat {

    let message = NSAttributedString(string: self.text!,
                                     attributes: [.font: self.font!])

    let labelWidth = self.bounds.width
    // Create instances of NSLayoutManager, NSTextContainer and NSTextStorage
    let labelSize = CGSize(width: labelWidth, height: .infinity)
    let layoutManager = NSLayoutManager()
    let textContainer = NSTextContainer(size: labelSize)
    let textStorage = NSTextStorage(attributedString: message)

    // Configure layoutManager and textStorage
     layoutManager.addTextContainer(textContainer)
    textStorage.addLayoutManager(layoutManager)

    // Configure textContainer
    textContainer.lineFragmentPadding = 0.0
    textContainer.lineBreakMode = .byWordWrapping
    textContainer.maximumNumberOfLines = 0

    let lastGlyphIndex = layoutManager.glyphIndexForCharacter(at: message.length - 1)
    let lastLineFragmentRect = layoutManager.lineFragmentUsedRect(forGlyphAt: lastGlyphIndex,
                                                                  effectiveRange: nil)

    return lastLineFragmentRect.maxX
}

I have tried this line of code, and it's not working for orientation landscape. How can I fix this problem? Does anyone have this issue?


Solution

  • It appears like the issue is due to the fact that your getLasLineWidth() func is not taking into account the paragraph styling you're setting.

    You may be able to fix the problem by changing this:

    func getLasLineWidth() -> CGFloat {
    
        let message = NSAttributedString(string: self.text!,
                                         attributes: [.font: self.font!])
    

    to this:

    func getLasLineWidth() -> CGFloat {
    
        guard let message = self.attributedText else { return CGFloat.zero }
    

    I've only done some quick testing, but it looks like this should do it.