Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

String boundingRect calculated height doesn't match UITextView content height

I have a UITableView with variably sized cells. The height is based on a block of text that I need to display so I need to measure the text.

I'm just using some Lorem Ipsum text:

"Nullam est elit, rutrum volutpat scelerisque eu, tincidunt ut magna. Quisque sit amet odio quis eros lobortis cursus. Phasellus mauris augue, mattis a posuere sit amet, dictum sit amet ipsum. Praesent velit sapien, tristique ut pellentesque eget, venenatis in est. Curabitur accumsan lacus nec ultricies finibus. In commodo, turpis at auctor lobortis, augue ipsum tincidunt lorem, vitae fringilla libero magna eget tortor. Sed et ultrices odio, et viverra diam. Mauris semper non lorem varius sollicitudin. Maecenas nec dui lectus. In hac habitasse platea dictumst. Quisque sapien ex, pretium id vehicula eget, tempus at nisl. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Aliquam vel sollicitudin velit, efficitur accumsan sem. Quisque id urna blandit, cursus justo sed, aliquet velit. Nullam id ipsum pellentesque, gravida nulla ut, tempor libero."

When I call ceil(text.height()) it returns 386.0 tall, but when I put that text into the UITextView and print out the content size of the UITextView it says the content is 422.0 tall. (i.e. my text is getting cut off because the UITextView isn't tall enough to display everything.)

Why is there a difference?

I'm using the following String extension to calculate the height of the text:

extension String {

    func height(withConstrainedWidth width: CGFloat, font: UIFont) -> CGFloat {
        let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude)
        let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)

        return boundingBox.height
    }

}

Then in tableView(heightForRowAt:) I calculate the height of the text and add it to the space above and below the textview to get the full cell height (this was more elegant before I started debugging this):

let textviewWidth = self.view.frame.size.width-CGFloat(32)
let spaceAboveTextView = CGFloat(45)
let spaceBelowTextView = CGFloat(16)
let textHeight = ceil(text.height(withConstrainedWidth: textviewWidth, font: UIFont.systemFont(ofSize: 17.0)))
let height = spaceAboveTextView + textHeight + spaceBelowTextView

I've verified that the UITextView is using the System Font of size 17, which matches with my code above.

I've verified the frame of the UITextView (after being displayed) is (16.0, 45.0, 382.0, 385.6667) so the spaceAboveTextView=45 is accurate and the width=382 is accurate. I've also checked the constraints on the UITextView and it has a bottom constraint of 8pt to the margin and the margin is 8pt for a total of 16pt in the spaceBelowTextView as well.

So, what am I doing wrong?

like image 527
Kenny Wyland Avatar asked Jul 02 '26 10:07

Kenny Wyland


1 Answers

Most likely you have a problem because you forgot to factor in the textContainerInset (maybe also other insets of your text view).

By default, they are 8 from top, left and right.

Try to change your code to this:

let textviewWidth = self.view.frame.size.width-CGFloat(32)-textView.textContainerInset.left-textView.textContainerInset.right
let spaceAboveTextView = CGFloat(45)+textView.textContainerInset.top
// bottom space is 0 by default. But lets add it just in case ;)
let spaceBelowTextView = CGFloat(16)+textView.textContainerInset.bottom
let textHeight = ceil(text.height(withConstrainedWidth: textviewWidth, font: UIFont.systemFont(ofSize: 17.0)))
let height = spaceAboveTextView + textHeight + spaceBelowTextView

I just tested this solution and it works for me with system font of size 17. Please let me know if this doesn't work!

like image 117
Andriy Gordiychuk Avatar answered Jul 05 '26 01:07

Andriy Gordiychuk



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!