07 Jul 2009

Calculating Height of Multi-Line Text on the iPhone SDK


If you've done some text layout on iPhone, you'll know that the documentation isn't really the greatest and clearest. The most frequently annoying thing about text layout is that there are these NSString UIStringDrawing additions that you would think can help you determine the size required to render a piece of text with a given font.

Specifically:

- (CGSize)sizeWithFont:(UIFont *)font
- (CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size
- (CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size lineBreakMode:(UILineBreakMode)lineBreakMode
- (CGSize)sizeWithFont:(UIFont *)font forWidth:(CGFloat)width lineBreakMode:(UILineBreakMode)lineBreakMode


Only one of the four above gives you sizes with multi-line text. Worse still, even if you choose the right one, you probably will end up passing the wrong thing into the size parameter.

In order to get the height of a piece of multi line text constrained by a given width, you must do this:

CGSize boundingSize = CGSizeMake(desiredWidth, CGFLOAT_MAX);
CGSize requiredSize = [someText sizeWithFont:someFont
constrainedToSize:boundingSize
lineBreakMode:UILineBreakModeWordWrap];
CGFloat requiredHeight = requiredSize.height;


Things to note:

  1. You must pass in CGFLOAT_MAX (or a big number) for the height, otherwise your text will never flow outside of the boundingSize. This is the bit I always get wrong.

  2. All the other sizeWithFont methods do not work with multi-line text. It says so in the documentation, even though it is not easy to spot.

  3. You must use UILineBreakModeWordWrap for the lineBreakMode



You can reply to me about this on Twitter: