How to calculate UILabel height dynamically?

I want to calculate the number of lines and the height of a UILabel dynamically from the given text for this.

+71
ios iphone uilabel label
Aug 24 '11 at 10:32
source share
15 answers

try it

// UILabel *myLabel; CGSize labelSize = [myLabel.text sizeWithFont:myLabel.font constrainedToSize:myLabel.frame.size lineBreakMode:NSLineBreakByWordWrapping]; CGFloat labelHeight = labelSize.height; int lines = [myLabel.text sizeWithFont:myLabel.font constrainedToSize:myLabel.frame.size lineBreakMode:NSLineBreakByWordWrapping].height/16; // '16' is font size 

or

 int lines = labelHeight/16; NSLog(@"lines count : %i \n\n",lines); 

or

 int lines = [myLabel.text sizeWithFont:myLabel.font constrainedToSize:myLabel.frame.size lineBreakMode:UILineBreakModeWordWrap].height /myLabel.font.pointSize; //fetching font size from font 

Using categories, just create a category class named

UILabel + UILabelDynamicHeight.h

UILabel + UILabelDynamicHeight.m

No more stress in calculating heights. Review the information below.

Updates for iOS7 and above, iOS 7 below: dynamically calculate UILabel height

 #define SYSTEM_VERSION_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame) #define SYSTEM_VERSION_GREATER_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending) #define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending) #define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending) #define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending) #define iOS7_0 @"7.0" 

UILabel + UILabelDynamicHeight.h

 #import <UIKit/UIKit.h> @interface UILabel (UILabelDynamicHeight) #pragma mark - Calculate the size the Multi line Label /*====================================================================*/ /* Calculate the size of the Multi line Label */ /*====================================================================*/ /** * Returns the size of the Label * * @param aLabel To be used to calculte the height * * @return size of the Label */ -(CGSize)sizeOfMultiLineLabel; @end 

UILabel + UILabelDynamicHeight.m

 #import "UILabel+UILabelDynamicHeight.h" @implementation UILabel (UILabelDynamicHeight) #pragma mark - Calculate the size,bounds,frame of the Multi line Label /*====================================================================*/ /* Calculate the size,bounds,frame of the Multi line Label */ /*====================================================================*/ /** * Returns the size of the Label * * @param aLabel To be used to calculte the height * * @return size of the Label */ -(CGSize)sizeOfMultiLineLabel{ //Label text NSString *aLabelTextString = [self text]; //Label font UIFont *aLabelFont = [self font]; //Width of the Label CGFloat aLabelSizeWidth = self.frame.size.width; if (SYSTEM_VERSION_LESS_THAN(iOS7_0)) { //version < 7.0 return [aLabelTextString sizeWithFont:aLabelFont constrainedToSize:CGSizeMake(aLabelSizeWidth, MAXFLOAT) lineBreakMode:NSLineBreakByWordWrapping]; } else if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(iOS7_0)) { //version >= 7.0 //Return the calculated size of the Label return [aLabelTextString boundingRectWithSize:CGSizeMake(aLabelSizeWidth, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{ NSFontAttributeName : aLabelFont } context:nil].size; } return [self bounds].size; } @end 
+81
Aug 24 '11 at 10:40
source share

Calling -sizeToFit on a UILabel instance will automatically resize it to fit the displayed text, without the need for calculation. If you need a size, you can get it from the label frame property after that.

 label.numberOfLines = 0; // allows label to have as many lines as needed label.text = @"some long text"; [label sizeToFit]; NSLog(@"Label frame is: %@", NSStringFromCGRect(label.frame)); 
+51
Aug 24 2018-11-11T00:
source share

To summarize, you can calculate the height of the label using its string and calling boundingRectWithSize . You must provide font as an attribute and include .usesLineFragmentOrigin for multi-line labels.

 let labelWidth = label.frame.width let maxLabelSize = CGSize(width: labelWidth, height: CGFloat.greatestFiniteMagnitude) let actualLabelSize = label.text!.boundingRect(with: maxLabelSize, options: [.usesLineFragmentOrigin], attributes: [.font: label.font], context: nil) let labelHeight = actualLabelSize.height(withWidth:labelWidth) 

Some extensions for this:

Swift version:

 extension UILabel { func textHeight(withWidth width: CGFloat) -> CGFloat { guard let text = text else { return 0 } return text.height(withWidth: width, font: font) } func attributedTextHeight(withWidth width: CGFloat) -> CGFloat { guard let attributedText = attributedText else { return 0 } return attributedText.height(withWidth: width) } } extension String { func height(withWidth width: CGFloat, font: UIFont) -> CGFloat { let maxSize = CGSize(width: width, height: CGFloat.greatestFiniteMagnitude) let actualSize = self.boundingRect(with: maxSize, options: [.usesLineFragmentOrigin], attributes: [.font : font], context: nil) return actualSize.height } } extension NSAttributedString { func height(withWidth width: CGFloat) -> CGFloat { let maxSize = CGSize(width: width, height: CGFloat.greatestFiniteMagnitude) let actualSize = boundingRect(with: maxSize, options: [.usesLineFragmentOrigin], context: nil) return actualSize.height } } 

Objective-C Version:

UILabel + Utility.h

 #import <UIKit/UIKit.h> @interface UILabel (Utility) - (CGFloat)textHeightForWidth:(CGFloat)width; - (CGFloat)attributedTextHeightForWidth:(CGFloat)width; @end 

UILabel + Utility.m

 @implementation NSString (Utility) - (CGFloat)heightForWidth:(CGFloat)width font:(UIFont *)font { CGSize maxSize = CGSizeMake(width, CGFLOAT_MAX); CGSize actualSize = [self boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : font} context:nil].size; return actualSize.height; } @end @implementation NSAttributedString (Utility) - (CGFloat)heightForWidth:(CGFloat)width { CGSize maxSize = CGSizeMake(width, CGFLOAT_MAX); CGSize actualSize = [self boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin context:nil].size; return actualSize.height; } @end @implementation UILabel (Utility) - (CGFloat)textHeightForWidth:(CGFloat)width { return [self.text heightForWidth:width font:self.font]; } - (CGFloat)attributedTextHeightForWidth:(CGFloat)width { return [self.attributedText heightForWidth:width]; } @end 
+30
Dec 22 '15 at 20:01
source share

The current solution is deprecated with iOS 7.

Here is the updated solution:

 + (CGFloat)heightOfCellWithIngredientLine:(NSString *)ingredientLine withSuperviewWidth:(CGFloat)superviewWidth { CGFloat labelWidth = superviewWidth - 30.0f; // use the known label width with a maximum height of 100 points CGSize labelContraints = CGSizeMake(labelWidth, 100.0f); NSStringDrawingContext *context = [[NSStringDrawingContext alloc] init]; CGRect labelRect = [ingredientLine boundingRectWithSize:labelContraints options:NSStringDrawingUsesLineFragmentOrigin attributes:nil context:context]; // return the calculated required height of the cell considering the label return labelRect.size.height; } 

The reason my solution is set up this way is because I use a UITableViewCell and dynamically resize the cell relative to how much space this label will take.

+17
Jul 30 '13 at 19:58
source share

Without calling sizeToFit, you can do this all numerically with a very paid and gaming solution:

 + (CGFloat)heightForText:(NSString*)text font:(UIFont*)font withinWidth:(CGFloat)width { CGSize size = [text sizeWithAttributes:@{NSFontAttributeName:font}]; CGFloat area = size.height * size.width; CGFloat height = roundf(area / width); return ceilf(height / font.lineHeight) * font.lineHeight; } 

I use it a lot for UITableViewCells that have dynamically distributed heights.

Also solves the problem with attributes @Salman Zaidi.

+8
Feb 17 '15 at 1:14
source share

Copy and paste this method and use it like:

 [lblText setFrame:CGRectMake(lblText.frame.origin.x, lblText.frame.origin.y, width, [self getLabelHeight:lblText])]; - (CGFloat)getLabelHeight:(UILabel*)label { CGSize constraint = CGSizeMake(label.frame.size.width, CGFLOAT_MAX); CGSize size; NSStringDrawingContext *context = [[NSStringDrawingContext alloc] init]; CGSize boundingBox = [label.text boundingRectWithSize:constraint options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:label.font} context:context].size; size = CGSizeMake(ceil(boundingBox.width), ceil(boundingBox.height)); return size.height; } 
+6
Jul 22 '16 at 13:14
source share
 CGSize maxSize = CGSizeMake(lbl.frame.size.width, CGFLOAT_MAX); CGSize requiredSize = [lbl sizeThatFits:maxSize]; CGFloat height=requiredSize.height 
+4
Feb 27 '16 at 13:17
source share

You need to create a String extension and call this method

 func height(withConstrainedWidth width: CGFloat, font: UIFont) -> CGFloat { let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude) let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil) return ceil(boundingBox.height) } 

You must send the width of your label

+1
Sep 23 '17 at 11:57
source share

Swift 4 To get the height for NSAttributedString, use this function below. Where width is the width of your UILabel or UITextView

 func getHeight(for attributedString: NSAttributedString, font: UIFont, width: CGFloat) -> CGFloat { let textStorage = NSTextStorage(attributedString: attributedString) let textContainter = NSTextContainer(size: CGSize(width: width, height: CGFloat.greatestFiniteMagnitude)) let layoutManager = NSLayoutManager() layoutManager.addTextContainer(textContainter) textStorage.addLayoutManager(layoutManager) textStorage.addAttribute(NSAttributedStringKey.font, value: font, range: NSMakeRange(0, textStorage.length)) textContainter.lineFragmentPadding = 0.0 layoutManager.glyphRange(for: textContainter) return layoutManager.usedRect(for: textContainter).size.height } 

To get the height for String, use this function, it is almost identical to the previous method:

 func getHeight(for string: String, font: UIFont, width: CGFloat) -> CGFloat { let textStorage = NSTextStorage(string: string) let textContainter = NSTextContainer(size: CGSize(width: width, height: CGFloat.greatestFiniteMagnitude)) let layoutManager = NSLayoutManager() layoutManager.addTextContainer(textContainter) textStorage.addLayoutManager(layoutManager) textStorage.addAttribute(NSAttributedStringKey.font, value: font, range: NSMakeRange(0, textStorage.length)) textContainter.lineFragmentPadding = 0.0 layoutManager.glyphRange(for: textContainter) return layoutManager.usedRect(for: textContainter).size.height } 
+1
Feb 12 '18 at 15:57
source share

In my case, I used a fixed-size header for each section, but with a dynamic size in every headline. The height of the cell depends on the height of the inscription.

Work with:

 tableView.estimatedRowHeight = SomeNumber tableView.rowHeight = UITableViewAutomaticDimension 

It works , but when used:

 tableView.reloadSections(IndexSet(integer: sender.tag) , with: .automatic) 

when many headers are not reset, many errors are created, such as duplicate headers (heading type x is lower than the same type) and strange animations when the framework is reloaded by animation even when used with the .none type (FYI, fixed heading height and cell height work )

The solution uses the heightForRowAt and calculates the height of the label itself (plus the animation looks much better). Remember that height is called first .

 func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { let object = dataDetailsController.getRowObject(forIndexPath: indexPath) let label = UILabel(frame: tableView.frame) let font = UIFont(name: "HelveticaNeue-Bold", size: 25) label.text = object?.name label.font = font label.numberOfLines = 0 label.textAlignment = .center label.sizeToFit() let size = label.frame.height return Float(size) == 0 ? 34 : size } 
0
Jun 19 '17 at 20:31 on
source share

This is the extension I use to calculate multi-line heights of UILabel, this is the edited snippet from the previous column:

 extension UILabel { func estimatedHeight(forWidth: CGFloat, text: String, ofSize: CGFloat) -> CGFloat { let size = CGSize(width: forWidth, height: CGFloat(MAXFLOAT)) let options = NSStringDrawingOptions.usesFontLeading.union(.usesLineFragmentOrigin) let attributes = [NSFontAttributeName: UIFont.systemFont(ofSize: ofSize)] let rectangleHeight = String(text).boundingRect(with: size, options: options, attributes: attributes, context: nil).height return ceil(rectangleHeight) } } 
0
Aug 30 '17 at 10:52 on
source share

If you use UILabel with attributes, you can try the textRect(forBounds:limitedToNumberOfLines) .

This is my example:

 let label = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 30)) label.numberOfLines = 0 label.text = "Learn how to use RxSwift and RxCocoa to write applications that can react to changes in your underlying data without you telling it to do so." let rectOfLabel = label.textRect(forBounds: CGRect(x: 0, y: 0, width: 100, height: CGFloat.greatestFiniteMagnitude), limitedToNumberOfLines: 0) let rectOfLabelOneLine = label.textRect(forBounds: CGRect(x: 0, y: 0, width: 100, height: CGFloat.greatestFiniteMagnitude), limitedToNumberOfLines: 1) let heightOfLabel = rectOfLabel.height let heightOfLine = rectOfLabelOneLine.height let numberOfLines = Int(heightOfLabel / heightOfLine) 

And my results on the playground:

enter image description here

0
Apr 14 '19 at 16:08
source share

Call label.sizeToFit and then label.layoutIfNeeded()

Then you should get the correct height with label.frame.height

0
Jun 28 '19 at 12:12
source share

To make UILabel match dynamic content, you can use the lines property in the property inspector and set it to 0.

And you do not need to do any coding for this.

For more details, you can check out the demo video below.

https://www.youtube.com/watch?v=rVeDS_OGslU

-one
Apr 7 '19 at 11:18
source share

if you want the label to accept dynamic strings you can use this

 label.numberOfLines = 0; // allows label to have as many lines as needed label.text = @"some long text "; [label sizeToFit]; NSLog(@"Label frame is: %@", NSStringFromCGRect(label.frame)); 
-2
Mar 12 '17 at 2:59 a.m.
source share



All Articles