3

This question has been asked numerous times, but the two or three answers repeatedly given don't seem to work.

The issue is: A `UITextView that contains some arbitrary text. After some action, the UITextView needs to resize both horizontally and vertically to snugly fit the text.

Answers on other questions give values which appear to be about the same width/height of the text; however, when the UITextView is resized to the calculated size, it's not quite right and the text line-breaks differently than it did originally.

Suggested methods include using – sizeWithFont:constrainedToSize: and other NSString methods, sizeThatFits: method of the UITextView (this gives a more correct height, but the full width of the view), and the contentSize property of the text view (also gives the wrong width).

Is there an accurate way to determine the width of a UITextView's text? or is there some hidden padding in the text view that makes the actually width the text fits in smaller? Or something else I'm completely missing?

Anthony Mattox
  • 7,048
  • 6
  • 43
  • 59
  • Out of curiosity, how far off are the results if you use the sizeWithFont method? UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(20, 20, 300, 200)]; textView.font = [UIFont systemFontOfSize:10.0f]; CGSize textViewSize = [textView.text sizeWithFont:[UIFont systemFontOfSize:10.0f] constrainedToSize:CGSizeMake(textView.frame.size.width - (textView.contentInset.left + textView.contentInset.left), MAXFLOAT) lineBreakMode:UILineBreakModeWordWrap]; – jamie-wilson Aug 09 '12 at 23:30
  • It's hard to say exactly because I don't have the correct number to compare it to. The content insets are all zero. The size returned b sizeWithFont is too small so it adds extra breaks. If I increment the width that I'm setting the text view [textView.text sizeWithFont:font constrainedToSize:textView.frame.size]+fudge, sixteen consistently seems to be the magic number that gives the correct size. That does not work though if the text broke in the middle of a word rather than at a space. In which case the sizeWithFont is correct. – Anthony Mattox Aug 10 '12 at 13:30
  • Perhaps the space characters are not considered by sizeWithFont but do effect how each line fits into the uiTextView? – Anthony Mattox Aug 10 '12 at 13:30

1 Answers1

0

I noticed the same problem: - sizeWithFont:constrainedToSize: on NSString will use different line breaks than a UITextView of the same width.

Here is my solution, though I'd like to find something cleaner.

    UITextView *tv = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, myMaxWidth, 100)]; // height resized later.
    tv.font = myFont;
    tv.text = @"."; // First find the min height if there is only one line.
    [tv sizeToFit];
    CGFloat minHeight = tv.contentSize.height;
    tv.text = myText; // Set the real text
    [tv sizeToFit];
    CGRect frame = tv.frame;
    frame.size.height = tv.contentSize.height;
    tv.frame = frame;
    CGFloat properHeight = tv.contentSize.height;
    if (properHeight > minHeight) { // > one line
        while (properHeight == tv.contentSize.height) {
            // Reduce width until height increases because more lines are needed
            frame = tv.frame;
            frame.size.width -= 1;
            tv.frame = frame;
        }
        // Add back the last point. 
        frame = tv.frame;
        frame.size.width += 1;
        tv.frame = frame;
    }
    else { // single line: ask NSString + fudge.
        // This is needed because a very short string will never break 
        // into two lines.
        CGSize tsz = [myText sizeWithFont:myFont constrainedToSize:tv.frame.size];
        frame = tv.frame;
        frame.size.width = tsz.width + 18; // YMMV
        tv.frame = frame;
    }
Bart Whiteley
  • 1,426
  • 12
  • 10