Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to find UILabel's number of Lines

Tags:

iphone

I displayed the text in UILabel by using wrap method. Now I want to need to find the how many number of line is there in UILabel.

If there is any possible way to find the UILabel's number of lines count.

Thanks.

like image 618
Velmurugan Avatar asked Nov 13 '10 12:11

Velmurugan


2 Answers

As pointed out, this post relates how to get the height, rather than the number of lines. To get the number of lines,

  1. Get the height for a single letter, e.g. @"A".
  2. Divide the height of the string by the height obtained in 1 above.

E.g.

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 ^^^^^ 

As of iOS 7, the way of getting a label's desired height 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 the height is r.size.height. Note that font must be provided. You can put this into a category for NSString for convenience, e.g.

@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 

(Do memory management if not using ARC, btw.)

For iOS 6 and below:

Let's say you have a UILabel *myLabel and you want to find out the height of the label (with some tweaking, you can get the # of lines by dividing the height with some appropriate 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 that helps. If it doesn't work let me know and I'll dig further. Also, untested code, but worked from reference.

For a more complete example, here is code which I put in the viewDidLoad: method of 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]; 

The output from the NSLog goes:

2010-11-15 18:25:27.817 so_labelheight[728:307] labelHeight = 126.000000 
like image 59
Kalle Avatar answered Sep 29 '22 11:09

Kalle


For iOS7 and above, the officially sanctioned way to count the number of lines is to use 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 } 
like image 41
johnboiles Avatar answered Sep 29 '22 09:09

johnboiles