Label根据内容计算大小

引言

由于最近工作需要实现一个类似脉脉动态的界面,其中展开显示全文功能,需要动态计算Label的大小后决定隐藏或者显示,之前一直使- (CGSize)sizeWithFont:(UIFont *)font方法,而在iOS7中用方法- (CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options attributes:(nullable NSDictionary *)attributes context:(nullable NSStringDrawingContext *)context,但是在实际运用中发现还是有一点小误差的。

关键字:全文Label高度计算展开全文

1 函数介绍

1.1 描述

- (CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options attributes:(NSDictionary *)attributes context:(NSStringDrawingContext *)context;

根据上下文设定和显示特性计算并返回一个rect大小

1.2 参数

参数 说明
size 存放字符串的Label的size大小
options 字符串排版的选项(下文会说明)
attributes 文字属性设置,至少需要font属性
context 渲染上下文

1.2.1 关于options

options 说明
NSStringDrawingTruncatesLastVisibleLine 如果文本内容超出指定的矩形限制,文本将被截去并在最后一个字符后加上省略号。
NSStringDrawingUsesLineFragmentOrigin 启用自动换行
NSStringDrawingUsesFontLeading 计算行高时使用行间距
NSStringDrawingUsesDeviceMetrics 计算布局时使用图元字形(而不是印刷字体)
  • 一般我们使用NSStringDrawingUsesLineFragmentOriginNSStringDrawingUsesFontLeading即可。

2 使用

直接上代码

NSString *contentText = @"南美足联同意国民竞技队请求,沙佩科恩斯队将获南美杯冠军。南美足联同意国民竞技队请求,沙佩科恩斯队将获南美杯冠军。南美足联同意国民竞技队请求,沙佩科恩斯队将获南美杯冠军。";

UILabel *DisplayLabel = [[UILabel alloc] init];
DisplayLabel.numberOfLines = 0;
DisplayLabel.text = contentText;
DisplayLabel.textColor = [UIColor orangeColor];
DisplayLabel.font = [UIFont systemFontOfSize:17];
DisplayLabel.frame = CGRectMake(20, 70, 200, 200);
[DisplayLabel sizeToFit];
DisplayLabel.backgroundColor = [UIColor greenColor];
[self.view addSubview:DisplayLabel];
    
//至少设置一个font属性
UIFont *fnt = self.DisplayLabel.font;
NSDictionary *dict = @{NSFontAttributeName: fnt};
    
//在为达到高度的情况下只有label的宽度有约束作用,高度最多为1000
CGSize defineSize = CGSizeMake(DisplayLabel.bounds.size.width, 1000);
//rect内的size即为计算所得的label大小
CGRect rect = [contentText boundingRectWithSize:defineSize
                                            options:NSStringDrawingUsesLineFragmentOrigin | 
                                                    NSStringDrawingUsesFontLeading
                                         attributes:dict
                                            context:nil];

结果显示

Label根据内容计算大小_第1张图片
Simulator Screen Shot 2016年12月3日 下午3.00.13.png
  • 结果上会有小数点后一位的误差,需要各位爷自己调整下,如果有好的建议欢迎指教~

3 附加

  • 展开显示全文的功能有时候还能通过计算行数来实现,送上一个coreText下的计算行数及每行内容的方法
//数组内为每行的内容,数组的count为行数
- (NSArray *)getLinesArrayOfStringInLabel:(UILabel *)label{
    NSString *text = [label text];
    UIFont *font = [label font];
    //目的为了取到label的宽度
    CGRect rect = [label frame];
    
    CTFontRef myFont = CTFontCreateWithName(( CFStringRef)([font fontName]), [font pointSize], NULL);
    NSMutableAttributedString *attStr = [[NSMutableAttributedString alloc] initWithString:text];
    [attStr addAttribute:(NSString *)kCTFontAttributeName value:(__bridge  id)myFont range:NSMakeRange(0, attStr.length)];
    CFRelease(myFont);
    CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString(( CFAttributedStringRef)attStr);
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathAddRect(path, NULL, CGRectMake(0,0,rect.size.width,100000));
    CTFrameRef frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, 0), path, NULL);
    NSArray *lines = ( NSArray *)CTFrameGetLines(frame);
    NSMutableArray *linesArray = [[NSMutableArray alloc]init];
    for (id line in lines) {
        CTLineRef lineRef = (__bridge  CTLineRef )line;
        CFRange lineRange = CTLineGetStringRange(lineRef);
        NSRange range = NSMakeRange(lineRange.location, lineRange.length);
        NSString *lineString = [text substringWithRange:range];
        CFAttributedStringSetAttribute((CFMutableAttributedStringRef)attStr, lineRange, kCTKernAttributeName, (CFTypeRef)([NSNumber numberWithFloat:0.0]));
        CFAttributedStringSetAttribute((CFMutableAttributedStringRef)attStr, lineRange, kCTKernAttributeName, (CFTypeRef)([NSNumber numberWithInt:0.0]));
        [linesArray addObject:lineString];
    }
    CFRelease(frameSetter);
    CFRelease(frame);
    CFRelease(path);
    return (NSArray *)linesArray;
}


最后附上github的demo。
欢迎各位看官老爷指教~

你可能感兴趣的:(Label根据内容计算大小)