美文网首页
Label根据内容计算大小

Label根据内容计算大小

作者: 缺一门 | 来源:发表于2016-12-03 15:07 被阅读0次

    引言

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

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

    1 函数介绍

    1.1 描述

    - (CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options attributes:(NSDictionary<NSString *,id> *)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];
    

    结果显示

    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根据内容计算大小

          本文链接:https://www.haomeiwen.com/subject/iemwuttx.html