Reputation: 1410
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.
Upvotes: 12
Views: 7212
Reputation: 1712
There is a method in TTTAttributedLabel
called
+ (CGSize)sizeThatFitsAttributedString:withConstraints:limitedToNumberOfLines:
Basically,this method use some Core Text API to calculate the height, the key function is
CGSize CTFramesetterSuggestFrameSizeWithConstraints(
CTFramesetterRef framesetter,
CFRange stringRange,
CFDictionaryRef __nullable frameAttributes,
CGSize constraints,
CFRange * __nullable fitRange )
which I think ,is also used by
- (CGRect)textRectForBounds:limitedToNumberOfLines:
this is a workaround and I think there are better way...
static UILabel *label;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
label = [UILabel new];
});
label.attributedText = givenAttributedString;
CGRect rect = CGRectMake(0,0,givenWidth,CGFLOAT_MAX)
CGFloat height = [label textRectForBounds:rect
limitedToNumberOfLines:2].size.height;
Upvotes: 0
Reputation: 1270
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
Upvotes: 5
Reputation: 3012
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:
Here's how to use it
NSAttributedString *string = ...
CGFloat height = [string heightForWidth:320.0f];
You can use that height for your layout computations.
Upvotes: 6