Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to calculate the height of NSAttributedString, given width and number of lines?

I want to display 3 lines of NSAttributedString. Is there a way to figure out the needed height, based on width and number of lines?

And I don't want to create a UILabel to do the size calculation, since I want the calculation to be done in background thread.

like image 772
lichen19853 Avatar asked Sep 19 '13 06:09

lichen19853


2 Answers

I wonder why this is still unanswered. Anyhow, here's the fastest method that works for me.

Make an NSAttributedString Category called "Height". This should generate two files titled "NSAttributedString+Height.{h,m}"

In the .h file:

@interface NSAttributedString (Height)  
-(CGFloat)heightForWidth:(CGFloat)width;  
@end  

In the .m file:

-(CGFloat)heightForWidth:(CGFloat)width  
{  
    return ceilf(CGRectGetHeight([self boundingRectWithSize:CGSizeMake(width, CGFLOAT_MAX)
                                                    options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading
                                                    context:nil])) + 1;  
}

Here's what's happening:

  1. boundRectWithSize:options:context get's a rect constrained to a width you pass to the method. The NSStringDrawingUsesLineFragmentOrigin option tells it to expect multiline string.
  2. Then we fetch the height parameter from that rect.
  3. In iOS 7, this method returns decimals. We need a round figure. ceilf helps with that.
  4. We add an extra unit to the returning value.

Here's how to use it

NSAttributedString *string = ...
CGFloat height = [string heightForWidth:320.0f];

You can use that height for your layout computations.

like image 192
dezinezync Avatar answered Oct 06 '22 03:10

dezinezync


The answer by @dezinezync answers half of the question. You'll just have to calculate the maximum size allowed for your UILabel with the given width and number of lines.

First, get the height allowed based on number of lines:

let maxHeight = font.lineHeight * numberOfLines

Then calculate the bounding rect of the text you set based on the criteria:

let labelStringSize = yourText.boundingRectWithSize(CGSizeMake(CGRectGetWidth(self.frame), maxHeight),
            options: NSStringDrawingOptions.UsesLineFragmentOrigin,
            attributes: [NSFontAttributeName: font],
            context: nil).size
like image 35
tropicalfish Avatar answered Oct 06 '22 03:10

tropicalfish