Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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];
like image 716
greg Avatar asked Nov 11 '15 05:11

greg


1 Answers

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.

like image 103
greg Avatar answered Oct 18 '22 23:10

greg