1

I want to calculate the drawing rect for my attributed text which is assigned to a label so that label frame can be changed based on the size.

The attributed text assigned to label have custom font and paragraph info.

I used boundingRectWithSize API to calculate but this API is not working as expected. How this can be done in iOS?

Adding the code for understanding

self.textLabel.attributedText = [Utilities attributedStringFromText:[dbObject valueForKey:@"content"]];

//change the frame of the label according to content
CGSize maximumSize = CGSizeMake(320,9999);

CGSize textSize= [self.textLabel.attributedText boundingRectWithSize:maximumSize
                                                             options:NSStringDrawingUsesLineFragmentOrigin
                                                             context:nil].size;
4
  • What do you mean by "is not working as expected?" Commented Jun 17, 2014 at 14:09
  • @RobNapier: The height is appears less and my text is getting truncated. Commented Jun 17, 2014 at 14:10
  • And your layout code works correctly with non-custom fonts? How many points is it off by (always the same number of points)? It is truncated both vertically and horizontally? It has the same problems without NSStringDrawingUsesLineFragmentOrigin? Why have you chosen to use NSStringDrawingUsesLineFragmentOrigin? What have you tried already? Commented Jun 17, 2014 at 14:16
  • I didn't try with non custom code. I believe it is noting to do with font. If I set simply text attribute of the label and not attribute text then it works. Commented Jun 17, 2014 at 14:18

1 Answer 1

2

If textLabel uses a single font, you can supply it in the attributes (Using .UsesFontLeading or NSStringDrawingUsesFontLeading option).

Swift

let size:CGSize = self.textLabel.attributedText.string.boundingRectWithSize(
    CGSizeMake(self.textLabel.bounds.width, CGFloat.max),
    options: (.UsesLineFragmentOrigin | .UsesFontLeading),
    attributes: [NSFontAttributeName : font],
    context: nil).size

Putting it all together (get the font from the attributed text) in Swift:

self.textLabel.attributedText.enumerateAttribute(
    NSFontAttributeName,
    inRange: NSMakeRange(0, self.textLabel.attributedText.length),
    options: NSAttributedStringEnumerationOptions(0)) {
        (value:AnyObject!, range:NSRange, stop:UnsafeMutablePointer<ObjCBool>) -> Void in
        stop.initialize(true)
        if let font:UIFont = value as? UIFont {
            let size:CGSize = self.textLabel.attributedText.string.boundingRectWithSize(
                CGSizeMake(self.textLabel.bounds.width, CGFloat.max),
                options: (.UsesLineFragmentOrigin | .UsesFontLeading),
                attributes: [NSFontAttributeName : font],
                context: nil).size
            self.textHeight.constant = size.height // Use height
        }
}

Obj-C

CGSize size = [self.textLabel.attributedText.string
            boundingRectWithSize:CGSizeMake(self.textLabel.bounds.size.width,
                                            CGFLOAT_MAX)
            options:(NSStringDrawingUsesLineFragmentOrigin |
                     NSStringDrawingUsesFontLeading)
            attributes:@{NSFontAttributeName: font}
            context:nil].size;

Putting it all together (get the font from the attributed text) in Obj-C:

[self.textLabel.attributedText
 enumerateAttribute:NSFontAttributeName
 inRange:(NSRange){0, self.textLabel.attributedText.length}
 options:(NSAttributedStringEnumerationOptions)0
 usingBlock:^(id value, NSRange range, BOOL *stop) {
     *stop = YES;
     if( [value isKindOfClass:[UIFont class]]) {
         UIFont * font = (UIFont*)value;
         CGSize size = [self.textLabel.attributedText.string
                        boundingRectWithSize:CGSizeMake(self.textLabel.bounds.size.width,
                                                        CGFLOAT_MAX)
                        options:(NSStringDrawingUsesLineFragmentOrigin |
                                 NSStringDrawingUsesFontLeading)
                        attributes:@{NSFontAttributeName: font}
                        context:nil].size;
         self.textHeight.constant = size.height; // USe height
     }
 }];
Sign up to request clarification or add additional context in comments.

2 Comments

if a string contains emoji, it might gives you wrong height tho.
Attributed text may contain paragraphs, different fonts so this won't calculate size correctly. It's good only for simple cases.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.