I have recently begun work on an app using Swift in Xcode and am trying to create a text bubble. To do this, I need to get the width of the longest row of text in a multi-row UILabel. For example, if I have this text (I automatically set line breaks after a certain length):

Hello there, this is 
an example piece of text

I would like to return the width of the text in the second row. I have already tried using sizeToFit() which would drastically simplify my work, but because of my other code, this is not an option as it causes other problems (my code is below). Is there a purely programmatic way to get this value without using sizeToFit()? Any help would be much appreciated. My code:

bubbleContents.text = textMessage
bubbleContents.numberOfLines = 0
bubbleContents.lineBreakMode = .byWordWrapping

bubbleContents.bounds.size.width = 2000
var widthText = bubbleContents.intrinsicContentSize.width
bubbleContents.bounds.size.width = 266
print(textMessage)
print(widthText)
if widthText > 266 {
    let numRows = Int(widthText/266)
    print(numRows)
    //bubbleContents.frame.origin.y += CGFloat((Double(numRows)*10.25))
    var currentHeight = 44.0
    currentHeight += Double((Double(numRows)*20.5))
    bubbleContents.bounds.size.height = CGFloat(currentHeight)
    heightOfCell = Double(currentHeight)
    let originalTransform = self.bubbleContents.transform
    let scaledTransform = originalTransform
    let scaledAndTranslatedTransform = scaledTransform.translatedBy(x: 0, y: CGFloat(Double(numRows)*20.5))
    //self.bubbleContents.transform = scaledAndTranslatedTransform
}
else {
    heightOfCell = 44.0
}

bubble.frame = CGRect(x: 0, y: 0, width: Double(widthText + 30), height: heightOfCell - 4)
bubbleContents.center.y = bubble.center.y

Here is an image of what my current text bubbles look like:

Image

1 Answers

1
AamirR On Best Solutions

You can use NSAttributedString,boundingRect(with:options:context:) method, begin by creating NSAttributedString with attributes such as font of your UILabel

let attributes: [NSAttributedString.Key : Any] = [.font: bubbleContents.font]
let atStr = NSAttributedString(string: textMessage, attributes: attributes)

Now use atStr.boundingRect(with:options:context:) method, like so:

let bounds = CGSize(width: 266.0, height: .greatestFiniteMagnitude)
let bubbleSize = atStr.boundingRect(with: bounds, options: [.usesLineFragmentOrigin, .usesFontLeading, .usesDeviceMetrics], context: nil).size

Usage:

bubble.frame.size.width = bubbleSize.width
bubble.frame.size.height = max(bubbleSize.height, 44.0)