greg
greg

Reputation: 2006

Wrapping UITextView with boundingRectWithSize:

I'm trying to dynamically update the height of a UITextView using the following code but the result is consistently off by a few pixels which causes the text view to wrap but not be sized appropriately. Once another character (or two) is entered, the display updates appropriately.

I've looked over various posts (many are outdated because they reference deprecated sizeThatFits) and I don't see anything different. Those using boundingRectWithSize: (either NSString or NSAttributedString – of which I've tried both) look like the following:

CGRect boundingRect = [string boundingRectWithSize: CGSizeMake(CGRectGetWidth(textView.frame), CGFLOAT_MAX)
                                           options: NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
                                        attributes: @{
                                                      NSFontAttributeName : textView.font
                                                      }
                                           context: NULL];
float h = ceil(CGRectGetHeight(boundingRect));

textViewHeightLayoutConstraint.constant = h;

I know the first thing you're going to say is: insets. Here's my setup code:

textView.textContainerInset = UIEdgeInsetsZero;
textView.contentInset = UIEdgeInsetsZero;
textView.layoutMargins = UIEdgeInsetsZero;

Is there another insets setting?

Side note: I'm using MuseoSans as the font.

Hack Solution

I've "fixed" the issue by checking if the width is within a threshold (currently 9px from testing) and if it is, pretending that an extra line was added like so:

float fontHeight = ceil([@"lp" sizeWithAttributes: @{
                                                     NSFontAttributeName : textView.font
                                                    }].height);


if ((CGRectGetWidth(textView.frame) - ceil(CGRectGetWidth(boundingRect))) <= 9.f)
     h += fontHeight;

The above allows me to capture the maximum possible height and then force it's height on my text view. The text view does wrap appropriately and show the text on the next line.

Ideas?

Small Update

Added this with no effect:

NSMutableParagraphStyle *paragraphStyle = [NSParagraphStyle.defaultParagraphStyle mutableCopy];
paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;

CGRect boundingRect = [string boundingRectWithSize: CGSizeMake(CGRectGetWidth(textView.frame), CGFLOAT_MAX)
                                           options: NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
                                        attributes: @{
                                                      NSFontAttributeName : textView.font,
                                                      NSParagraphStyleAttributeName : paragraphStyle
                                                      }
                                           context: NULL];

Upvotes: 5

Views: 1630

Answers (1)

greg
greg

Reputation: 2006

I found the answer. It's in:

textView.textContainer.lineFragmentPadding

I needed to subtract that from my textView width. I guess there is another source of padding in addition to the 3 sets of insets and margins.

Upvotes: 9

Related Questions