Reputation: 735
I am trying to calculate the height of label programmatically.
A sample text in my case would look like:
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
The code I used to calculate label height:
-(CGFloat)getLabelHeightUsingWidth:(CGFloat)cellWidth
{
NSInteger fontSize = 16;
UIFont *descLabelFont = [UIFont fontWithName:@"MyFontName" size:fontSize];
NSString *description = <sample text provided above>;
CGSize constraint = CGSizeMake(width, CGFLOAT_MAX);
CGSize size;
NSStringDrawingContext *context = [[NSStringDrawingContext alloc] init];
CGSize boundingBox = [text boundingRectWithSize:constraint options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:font}
context:context].size;
size = CGSizeMake(ceil(boundingBox.width), ceil(boundingBox.height));
return size.height ;
}
For text content with single or no newline in it will give the proper height, but not with doublenewline as in my example text. When double newline is present, the calculated height returned is less than that of what is really needed. So, returned height will be less and original height when displayed will be more creating incorrect height issue for my table cell in which I am displaying the multiline string.
So, I inferred that the double newline could be the issue and tried to remove the double newline occurrences with single newline. Then, the height calculated was correct.
What is the proper way to handle this scenario?
Upvotes: 0
Views: 447
Reputation: 53
I'm seeing this happening also on a UILabel in a UIView in a vertical UIStackView. When there are 2 \n\n in the text, it won't resize it properly, it loses 1 line.
Upvotes: 1
Reputation: 77690
Hard to say exactly what's wrong... maybe you're (accidentally) not using the same font? maybe (accidentally) not using the exact same string?
It seems like a bit of an odd way to go about this anyway.
Give this a try:
LabelHeightViewController.h
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface LabelHeightViewController : UIViewController
@end
NS_ASSUME_NONNULL_END
LabelHeightViewController.m
#import "LabelHeightViewController.h"
@interface LabelHeightViewController ()
@property (strong, nonatomic) UILabel *myLabel;
@property (strong, nonatomic) UIView *redView;
@end
@implementation LabelHeightViewController
- (void)viewDidLoad {
[super viewDidLoad];
_myLabel = [UILabel new];
_redView = [UIView new];
_myLabel.translatesAutoresizingMaskIntoConstraints = NO;
_redView.translatesAutoresizingMaskIntoConstraints = NO;
_myLabel.numberOfLines = 0;
_myLabel.text = @"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n\nUt enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n\n\nExcepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";
UIFont *font = [UIFont fontWithName:@"Avenir-Book" size:16.0];
_myLabel.font = font;
// we're going to set the label width to 300
CGFloat w = 300.0;
// calculate the height
CGFloat h = [self getLabelHeight:_myLabel forWidth:w];
[self.view addSubview:_myLabel];
[self.view addSubview:_redView];
UILayoutGuide *g = self.view.layoutMarginsGuide;
[NSLayoutConstraint activateConstraints:@[
// constrain label Top: 40 / Leading: 12 / Width: w
[_myLabel.topAnchor constraintEqualToAnchor:g.topAnchor constant:40.0],
[_myLabel.leadingAnchor constraintEqualToAnchor:g.leadingAnchor constant:12.0],
[_myLabel.widthAnchor constraintEqualToConstant:w],
// constrain red view Top: label Top / Leading: label leading + 8
// Width: 20 / Height: h
[_redView.topAnchor constraintEqualToAnchor:_myLabel.topAnchor],
[_redView.leadingAnchor constraintEqualToAnchor:_myLabel.trailingAnchor constant:8.0],
[_redView.widthAnchor constraintEqualToConstant:20.0],
[_redView.heightAnchor constraintEqualToConstant:h],
]];
// so we can see the frames
_myLabel.backgroundColor = [UIColor yellowColor];
_redView.backgroundColor = [UIColor redColor];
}
-(CGFloat)getLabelHeight:(UILabel *)theLabel forWidth:(CGFloat)theWidth {
UIFont *descLabelFont = theLabel.font;
NSString *description = theLabel.text;
CGSize constraint = CGSizeMake(theWidth, CGFLOAT_MAX);
NSStringDrawingContext *context = [[NSStringDrawingContext alloc] init];
CGSize boundingBox = [description boundingRectWithSize:constraint
options:NSStringDrawingUsesLineFragmentOrigin
attributes:@{NSFontAttributeName:descLabelFont}
context:context].size;
return ceil(boundingBox.height);
}
@end
Result:
Notes:
the height of the Red view is set to the height returned by
-(CGFloat)getLabelHeight:(UILabel *)theLabel forWidth:(CGFloat)theWidth`
and the text has tow newlines - \n\n
- for the first "break" and 3 newlines - \n\n\n
- for the second break (for demonstration).
Upvotes: 0