How to find UILabel row count

I displayed the text in UILabel using the wrap method. Now I need to find the number of rows in UILabel.

If there is a possible way to find the number of rows in a UILabel string.

Thank.

+39
iphone
Nov 13 '10 at
source share
7 answers

As indicated, this post describes how to get the height, not the number of rows. To get the number of rows,

  • Get the height for a single letter, for example. @"A" .
  • Divide the row height by the height obtained at 1 above.

eg.

 CGFloat unitHeight = [@"A" heightForWidth:width usingFont:font]; CGFloat blockHeight = [text heightForWidth:width usingFont:font]; NSInteger numberOfLines = ceilf(blockHeight / unitHeight); // need to #include <math.h> for ^^^^^ 

Starting with iOS 7, the way to get the mark of the desired height has changed. To get the height, you can use the following code:

 NSStringDrawingContext *context = [[NSStringDrawingContext alloc] init]; CGSize labelSize = (CGSize){width, FLT_MAX}; CGRect r = [self boundingRectWithSize:labelSize options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: font} context:context]; 

where is the height of r.size.height . Please note that font must be provided. You can put this in a category for NSString for convenience, for example.

 @implementation NSString (HeightCalc) - (CGFloat)heightForWidth:(CGFloat)width usingFont:(UIFont *)font { NSStringDrawingContext *context = [[NSStringDrawingContext alloc] init]; CGSize labelSize = (CGSize){width, FLT_MAX}; CGRect r = [self boundingRectWithSize:labelSize options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: font} context:context]; return r.size.height; } @end 

(Memory management if ARC is not used, by the way.)

For iOS 6 and below:

Say you have UILabel *myLabel and you want to know the height of the label (with some tweaking, you can get # lines by dividing the height with some corresponding number, which depends on the font size).

 UILabel *myLabel; CGSize labelSize = [myLabel.text sizeWithFont:myLabel.font constrainedToSize:myLabel.frame.size lineBreakMode:UILineBreakModeWordWrap]; CGFloat labelHeight = labelSize.height; 

Hope this helps. If this does not help, let me know and I will dig further. Also, unverified code, but worked with a link.

For a more complete example, here is the code I entered in the viewDidLoad: method for a view controller:

 [super viewDidLoad]; UILabel *myLabel = [[UILabel alloc] initWithFrame:CGRectMake(50,50,200,350)]; myLabel.numberOfLines = 0; myLabel.lineBreakMode = UILineBreakModeWordWrap; myLabel.text = @"This is some text in a UILabel which is long enough to wrap around the lines in said UILabel. This is a test, this is only a test."; [self.view addSubview:myLabel]; CGSize labelSize = [myLabel.text sizeWithFont:myLabel.font constrainedToSize:myLabel.frame.size lineBreakMode:UILineBreakModeWordWrap]; CGFloat labelHeight = labelSize.height; NSLog(@"labelHeight = %f", labelHeight); [myLabel release]; 

Exiting NSLog is:

 2010-11-15 18:25:27.817 so_labelheight[728:307] labelHeight = 126.000000 
+50
Nov 13 '10 at 18:27
source share

For iOS7 and above, the officially authorized method for counting the number of lines is TextKit:

 func numberOfLinesForString(string: String, size: CGSize, font: UIFont) -> Int { let textStorage = NSTextStorage(string: string, attributes: [NSFontAttributeName: font]) let textContainer = NSTextContainer(size: size) textContainer.lineBreakMode = .ByWordWrapping textContainer.maximumNumberOfLines = 0 textContainer.lineFragmentPadding = 0 let layoutManager = NSLayoutManager() layoutManager.textStorage = textStorage layoutManager.addTextContainer(textContainer) var numberOfLines = 0 var index = 0 var lineRange : NSRange = NSMakeRange(0, 0) for (; index < layoutManager.numberOfGlyphs; numberOfLines++) { layoutManager.lineFragmentRectForGlyphAtIndex(index, effectiveRange: &lineRange) index = NSMaxRange(lineRange) } return numberOfLines } 
+13
May 04 '15 at 22:14
source share

The -sizeWithFont:constrainedToSize:lineBreakMode now deprecated. Now you will want to use the -boundingRectWithSize:options:attributes:context: method.

Here are some examples:

 CGSize boundingRectSize = CGSizeMake(widthToConstrainTo, CGFLOAT_MAX); NSDictionary *attributes = @{NSFontAttributeName : [UIFont fontWithName:fontName size:14]}; CGRect labelSize = [labelString boundingRectWithSize:boundingRectSize options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:attributes context:nil]; 

In the above example, I know the width that I want to limit to the label, but since I'm not sure about the height, I just increase the height parameter with CGFLOAT_MAX . For options you need to use NSStringDrawingUsesLineFragmentOrigin and NSStringDrawingUsesFontLeading if you are trying to calculate the size of the label, which can be any number of lines.

+7
Jul 03 '14 at 10:18
source share

sizeWithFont deprecated in iOS 7, you can use this instead:

 - (int)lineCountForText:(NSString *) text { UIFont *font = ... CGRect rect = [text boundingRectWithSize:CGSizeMake(200, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : font} context:nil]; return ceil(rect.size.height / font.lineHeight); } 
+6
Aug 22 '14 at
source share

If you are looking for this answer in Swift 2 + / iOS 8, it will look like this:

 func numberOfLinesInLabel(yourString: String, labelWidth: CGFloat, labelHeight: CGFloat, font: UIFont) -> Int { let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.minimumLineHeight = labelHeight paragraphStyle.maximumLineHeight = labelHeight paragraphStyle.lineBreakMode = .ByWordWrapping let attributes: [String: AnyObject] = [NSFontAttributeName: font, NSParagraphStyleAttributeName: paragraphStyle] let constrain = CGSizeMake(labelWidth, CGFloat(Float.infinity)) let size = yourString.sizeWithAttributes(attributes) let stringWidth = size.width let numberOfLines = ceil(Double(stringWidth/constrain.width)) return Int(numberOfLines) } 
+5
Dec 14 '15 at 17:05
source share

(I originally posted my answer here , but does not have enough reputation to comment or mark duplicates.)

The other answers I found do not respect the numberOfLines UILabel property if it is set to a value 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 (e.g. 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)
+2
Jun 03 '15 at 17:34
source share
 func getHeight(text: NSString, width:CGFloat, font: UIFont) -> CGFloat { let rect = text.boundingRect(with: CGSize.init(width: width, height: CGFloat.greatestFiniteMagnitude), options: ([NSStringDrawingOptions.usesLineFragmentOrigin,NSStringDrawingOptions.usesFontLeading]), attributes: [NSFontAttributeName:font], context: nil) return rect.size.height } 

text: label whose height you need to find with the given string

width: UILabel width

font: UILabel font

0
Sep 19 '17 at 12:18
source share



All Articles