How to find the actual number of rows of a UILabel?

How can I find the actual number of UILabel lines after I initialized it with text and a font ? I set the numberOfLines property to 0 , so it will expand until many lines are needed. But then, how can I find out how many lines it received after I set it to text ?

I found similar questions, but none of them give a short answer, and it seems to me that it is really easy to get it without any overhead when juggling with boundingRectWithSize or sizeWithFont , ...

+58
ios uilabel
Jan 23 '15 at 11:18
source share
13 answers

First set the text to UILabel

First option:

First, calculate the height of the text according to the font:

 NSInteger lineCount = 0; CGSize labelSize = (CGSize){yourLabel.frame.size.width, MAXFLOAT}; CGRect requiredSize = [self boundingRectWithSize:labelSize options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: yourLabel.font} context:nil]; 

Now calculate the number of lines:

 int charSize = lroundf(yourLabel.font.lineHeight); int rHeight = lroundf(requiredSize.height); lineCount = rHeight/charSize; NSLog(@"No of lines: %i",lineCount); 

The second option:

  NSInteger lineCount = 0; CGSize textSize = CGSizeMake(yourLabel.frame.size.width, MAXFLOAT); int rHeight = lroundf([yourLabel sizeThatFits:textSize].height); int charSize = lroundf(yourLabel.font.lineHeight); lineCount = rHeight/charSize; NSLog(@"No of lines: %i",lineCount); 
+50
Jan 23 '15 at 11:30
source share

None of this helped me. Below one did

Swift 4.2:

 extension UILabel { func calculateMaxLines() -> Int { let maxSize = CGSize(width: frame.size.width, height: CGFloat(Float.infinity)) let charSize = font.lineHeight let text = (self.text ?? "") as NSString let textSize = text.boundingRect(with: maxSize, options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font: font], context: nil) let linesRoundedUp = Int(ceil(textSize.height/charSize)) return linesRoundedUp } } 

Swift 4 / 4.1:

 extension UILabel { func calculateMaxLines() -> Int { let maxSize = CGSize(width: frame.size.width, height: CGFloat(Float.infinity)) let charSize = font.lineHeight let text = (self.text ?? "") as NSString let textSize = text.boundingRect(with: maxSize, options: .usesLineFragmentOrigin, attributes: [.font: font], context: nil) let linesRoundedUp = Int(ceil(textSize.height/charSize)) return linesRoundedUp } } 

Swift 3:

 extension UILabel { func calculateMaxLines() -> Int { let maxSize = CGSize(width: frame.size.width, height: CGFloat(Float.infinity)) let charSize = font.lineHeight let text = (self.text ?? "") as NSString let textSize = text.boundingRect(with: maxSize, options: .usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil) let linesRoundedUp = Int(ceil(textSize.height/charSize)) return linesRoundedUp } } 
+59
Feb 14 '18 at 20:29
source share

Swift 5 (iOS 12.2)

Get the maximum number of lines needed for the label to display text without truncation.

 extension UILabel { var maxNumberOfLines: Int { let maxSize = CGSize(width: frame.size.width, height: CGFloat(MAXFLOAT)) let text = (self.text ?? "") as NSString let textHeight = text.boundingRect(with: maxSize, options: .usesLineFragmentOrigin, attributes: [.font: font], context: nil).height let lineHeight = font.lineHeight return Int(ceil(textHeight / lineHeight)) } } 

Get the maximum number of lines can be displayed in the label with limited borders. Use this property after assigning text to a label.

 extension UILabel { var numberOfVisibleLines: Int { let maxSize = CGSize(width: frame.size.width, height: CGFloat(MAXFLOAT)) let textHeight = sizeThatFits(maxSize).height let lineHeight = font.lineHeight return Int(ceil(textHeight / lineHeight)) } } 

using

 print(yourLabel.maxNumberOfLines) print(yourLabel.numberOfVisibleLines) 
+42
May 20, '17 at 13:29
source share

Here is the operational version of @Paresh solution:

 func lines(label: UILabel) -> Int { let textSize = CGSize(width: label.frame.size.width, height: CGFloat(Float.infinity)) let rHeight = lroundf(Float(label.sizeThatFits(textSize).height)) let charSize = lroundf(Float(label.font.lineHeight)) let lineCount = rHeight/charSize return lineCount } 

EDIT: I don't know why, but the code returns 2 more lines than the actual number of lines, for my solution, I just read them before returning lineCount.

+16
Jan 02 '15 at 18:52
source share

The other answers here do not match the numberOfLines UILabel property when it is set to something other than 0.

Here is another option you can add to your category or subclass:

 - (NSUInteger)lineCount { CGSize size = [self sizeThatFits:CGSizeMake(self.frame.size.width, CGFLOAT_MAX)]; return MAX((int)(size.height / self.font.lineHeight), 0); } 

Some notes:

  • I use this in UILabel with attributed text, without even setting the font property, and it works fine. Obviously, you ran into problems if you used multiple fonts in attributedText .
  • If you are subclassing UILabel to have custom edge inserts (for example, overriding drawTextInRect: which is a neat trick, I found here ), then you should not consider these inserts when calculating the size above. For example: CGSizeMake(self.frame.size.width - (self.insets.left + self.insets.right), CGFLOAT_MAX)
+10
Jun 03 '15 at 17:26
source share

Here is the Swift3 code here, you can determine the value of Int and get the height of the text size using (MAXFLOAT), and using this height, you can get the total height of the UILabel, and by highlighting this total height by the size of the character, you can get the actual number of UILabel lines.

 var lineCount: Int = 0 var textSize = CGSize(width: CGFloat(yourLabel.frame.size.width), height: CGFloat(MAXFLOAT)) var rHeight: Int = lroundf(yourLabel.sizeThatFits(textSize).height) var charSize: Int = lroundf(yourLabel.font.leading) lineCount = rHeight / charSize print("No of lines: \(lineCount)") 
+8
Apr 05 '17 at 11:35 on
source share

In response to @Prince, I now applied the category on UILabel as follows (note that I fixed some minor syntax errors in his answer that prevented the code from compiling):

UILabel + util.h

 #import <UIKit/UIKit.h> @interface UILabel (Util) - (NSInteger)lineCount; @end 

UILabel + Util.,

 #import "UILabel+Util.h" @implementation UILabel (Util) - (NSInteger)lineCount { // Calculate height text according to font NSInteger lineCount = 0; CGSize labelSize = (CGSize){self.frame.size.width, FLT_MAX}; CGRect requiredSize = [self.text boundingRectWithSize:labelSize options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: self.font} context:nil]; // Calculate number of lines int charSize = self.font.leading; int rHeight = requiredSize.size.height; lineCount = rHeight/charSize; return lineCount; } @end 
+4
Jan 23 '15 at 11:37
source share

You can find the total number of lines available on your custom label. Check this code ...

 NSInteger numberOfLines = [self lineCountForText:@"YOUR TEXT"]; - (int)lineCountForText:(NSString *) text { UIFont *font = [UIFont systemFontOfSize: 15.0]; int width=Your_LabelWidht; CGRect rect = [text boundingRectWithSize:CGSizeMake(width, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : font} context:nil]; return ceil(rect.size.height / font.lineHeight); } 
+4
Sep 18 '17 at 7:50
source share

It seems that the official site of the developer mentions one solution Counting lines of text in Objc. However, it is assumed that you have a link to a text view configured using the layout manager, text storage, and text container. Unfortunately, UILabel does not provide them to us, so we need to create them with the same configuration as UILabel.

I translated the Objc code into swift as follows. I think it works well.

 extension UILabel { var actualNumberOfLines: Int { let textStorage = NSTextStorage(attributedString: self.attributedText!) let layoutManager = NSLayoutManager() textStorage.addLayoutManager(layoutManager) let textContainer = NSTextContainer(size: self.bounds.size) textContainer.lineFragmentPadding = 0 textContainer.lineBreakMode = self.lineBreakMode layoutManager.addTextContainer(textContainer) let numberOfGlyphs = layoutManager.numberOfGlyphs var numberOfLines = 0, index = 0, lineRange = NSMakeRange(0, 1) while index < numberOfGlyphs { layoutManager.lineFragmentRect(forGlyphAt: index, effectiveRange: &lineRange) index = NSMaxRange(lineRange) numberOfLines += 1 } return numberOfLines } } 
+1
Aug 07 '19 at 18:42
source share

Xamarin.iOS

Thanks to everyone for the answers provided above.

This gets the number of visible lines.

 public static int VisibleLineCount(this UILabel label) { var textSize = new CGSize(label.Frame.Size.Width, nfloat.MaxValue); nfloat rHeight = label.SizeThatFits(textSize).Height; nfloat charSize = label.Font.LineHeight; return Convert.ToInt32(rHeight / charSize); } 

It turns out the actual number of lines that the text will occupy on the screen.

 public static int LineCount(this UILabel label) { var maxSize = new CGSize(label.Frame.Size.Width, nfloat.MaxValue); var charSize = label.Font.LineHeight; var text = (label.Text ?? "").ToNSString(); var textSize = text.GetBoundingRect(maxSize, NSStringDrawingOptions.UsesLineFragmentOrigin, new UIStringAttributes() { Font = label.Font }, null); return Convert.ToInt32(textSize.Height / charSize); } 

A helper method that I find useful for my use case.

 public static bool IsTextTruncated(this UILabel label) { if (label.Lines == 0) { return false; } return (label.LineCount() > label.Lines); } 

To get a more accurate number of rows:

  • Use font.lineHeight instead of font.pointSize
  • round () number of rows after division
0
Jun 23 '18 at 18:28
source share
 let l = UILabel() l.numberOfLines = 0 l.layer.frame.size.width = self.view.frame.width - 40 /*padding(20 + 20)*/ l.font = UIFont(name: "BwModelica-Bold", size: 16.0) l.text = "Random Any length Text!!" let noOfLines = ceil(l.intrinsicContentSize.width) / l.frame.width) let lbl_height = noOfLines * l.intrinsicContentSize.height 

This will be your exact dynamic cue height and row count. Good coding !!!

0
Jan 18 '19 at 8:22
source share

Please note that @ kurt-j's answer will not always work. In some cases, you will have to manually specify the width of the label. Since such cases exist, it is recommended that you have an optional width parameter, even if you are not using it ultimately.

Swift 4.2:

 extension UILabel { func calculateMaxLines(actualWidth: CGFloat?) -> Int { var width = frame.size.width if let actualWidth = actualWidth { width = actualWidth } let maxSize = CGSize(width: width, height: CGFloat(Float.infinity)) let charSize = font.lineHeight let text = (self.text ?? "") as NSString let textSize = text.boundingRect(with: maxSize, options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font: font], context: nil) let linesRoundedUp = Int(ceil(textSize.height/charSize)) return linesRoundedUp } } 
0
Mar 10 '19 at 20:02
source share

Xamarin iOS

 label.Text = text; var lineCount = 0; var textSize = new CGSize(label.Frame.Size.Width, float.MaxValue); var height = label.SizeThatFits(textSize).Height; var fontHeight = label.Font.LineHeight; lineCount = Convert.ToInt32(height / fontHeight); 
-one
Jan 30 '18 at 23:26
source share



All Articles