ZyusAn
ZyusAn

Reputation: 379

How to get exactly height of UILabel with line space?

I'm writing a expandable tableView header, I need to set the height of header accurately in tableView delegate method. I'm now using the following method to calculate the height of my header(a multi-line label):

CGRect calcuRect = [headerText boundingRectWithSize:CGSizeMake(myLabelWitdh, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:myLabelFont} context:nil];
CGFloat headerHeight = calcuRect.size.height;

However, I've found that the height calculated out is just about the text without include line space. So how can I get the line space height of the label? or how to get accurate height of UILabel with line space?

Upvotes: 6

Views: 8940

Answers (6)

agfa555
agfa555

Reputation: 950

Based on Rajan Maheshwari answer I wrote this function in Swift 3.0 for a generic label with the optional line height. Hope it helps.

func heightForLabel(_ text: String, font: UIFont, width: CGFloat, lineSpacing: CGFloat) -> CGFloat {
    let label = UILabel(frame: CGRect(x: 0, y: 0, width: width, height: CGFloat.greatestFiniteMagnitude))
    label.numberOfLines = 0
    label.lineBreakMode = NSLineBreakMode.byWordWrapping
    label.font = font
    if lineSpacing > 0.0 {
        let style = NSMutableParagraphStyle()
        style.lineSpacing = lineSpacing
        style.alignment = .center
        label.attributedText = NSAttributedString(string: text, attributes: [NSParagraphStyleAttributeName: style])
    } else {
        label.text = text
    }
    label.sizeToFit()
    return label.frame.height
}

Upvotes: 1

Rajan Maheshwari
Rajan Maheshwari

Reputation: 14571

You can get the exact height of UILabel with exactly passing the same font size and type and doing some calculations.
Here I used a UILabel with Helvetica font with font size 16.

Objective C

- (CGFloat)requiredHeight:(NSString*)labelText{

    UIFont *font = [UIFont fontWithName:@"Helvetica" size:16.0];
    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 200, CGFLOAT_MAX)];
    label.numberOfLines = 0;
    label.lineBreakMode = NSLineBreakByWordWrapping;
    label.font = font;
    label.text = labelText;
    [label sizeToFit];
    return label.frame.size.height;

}

Output

CGFloat size = [self requiredHeight:@"iOS Rocks"];
NSLog(@"%f",size);

size = [self requiredHeight:@"iOS Rocks\n"];
NSLog(@"%f",size);

Console Output

2016-04-10 01:37:46.812 testPro[6093:327503] 18.500000
2016-04-10 01:37:46.814 testPro[6093:327503] 37.000000

Swift 2.2

func requiredHeight(labelText:String) -> CGFloat {

    let font = UIFont(name: "Helvetica", size: 16.0)
    let label:UILabel = UILabel(frame: CGRectMake(0, 0, 200, CGFloat.max))
    label.numberOfLines = 0
    label.lineBreakMode = NSLineBreakMode.ByWordWrapping
    label.font = font
    label.text = labelText
    label.sizeToFit()
    return label.frame.height

}

Edit
Swift 3.0

func requiredHeight(labelText:String) -> CGFloat {

    let font = UIFont(name: "Helvetica", size: 16.0)
    let label:UILabel = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: .max))
    label.numberOfLines = 0
    label.lineBreakMode = .byWordWrapping
    label.font = font
    label.text = labelText
    label.sizeToFit()
    return label.frame.height

}

Upvotes: 9

ZyusAn
ZyusAn

Reputation: 379

In fact, I want to create an expandable section header in my table view, however in the delegate method:

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section

this method must return the exactly height of my label header, I use the following method to calculate the height, however the height do not include line space but only words height;

- (CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options attributes:(NSDictionary<NSString *, id> *)attributes context:(NSStringDrawingContext *)context;

Since know more about sizeToFit, here is a feasible answer

- (void)viewDidLoad {
    [super viewDidLoad];

    [self tableViewInit];
    [self headerInit];
}

- (void)tableViewInit {
    self.tableView = [[UITableView alloc] initWithFrame:self.view.bounds];
    [self.view addSubview:_tableView];
    self.tableView.dataSource = self;
    self.tableView.delegate = self;
}

- (void)headerInit {
    CGRect originSize = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, CGFLOAT_MIN);
    self.header = [[UILabel alloc] initWithFrame:originSize];
    self.header.lineBreakMode = NSLineBreakByWordWrapping | NSLineBreakByTruncatingTail;
    self.header.text = self.headerStr;
}

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
    if (self.showAll) {
        self.header.numberOfLines = 0;
        [self.header sizeToFit];
    } else {
        self.header.numberOfLines = 2;
        [self.header sizeToFit];
    }
    return self.header.bounds.size.height;
}

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    return self.header;
}

Upvotes: 0

Rubiya Faniband
Rubiya Faniband

Reputation: 370

    override func viewDidLayoutSubviews() {
          super.viewDidLayoutSubviews()
          sizeToFit()

        }
       func sizeToFit(){
            let header = customHeaderView
            let height = header.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height;
            var headerFrame = header.frame

            headerFrame.size.height = height
            header.frame = headerFrame
            tableView.tableHeaderView = header;



    }
Hope this will help you. 

Upvotes: 0

iPhone developer.
iPhone developer.

Reputation: 2132

Use below methods for same.

- (CGFloat)heightForWidth:(CGFloat)width usingFont:(UIFont *)font withText:(NSString *)aStrText
{
    CGSize labelSize = (CGSize){width, FLT_MAX};
    CGRect rect = [aStrText boundingRectWithSize:labelSize
                                         options:NSStringDrawingUsesLineFragmentOrigin
                                      attributes:@{NSFontAttributeName : font}
                                         context:nil];
    return rect.size.height;
}

Upvotes: 0

mathlete
mathlete

Reputation: 181

You need to resize the label frame. Try: [label sizeToFit];

Upvotes: 0

Related Questions