iOS一行文字与多行文字间距问题的解决方案

以下为NSAttributedString的属性,设置行间距为6

UIFont * font = [UIFont systemFontOfSize:14];
NSMutableParagraphStyle * paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineSpacing = 6;
paragraphStyle.alignment   = NSTextAlignmentCenter;
paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;
_defaultMessageAttribute =    @{
                                NSFontAttributeName:font,
                                NSParagraphStyleAttributeName:paragraphStyle
                                };

多行文字时显示正常,如下:
图片来自https://www.jianshu.com/p/ee6af597b27e

但是单行文字时就出现了问题,如下:
图片来自https://www.jianshu.com/p/ee6af597b27e

那么问题的解决思路为,当单行时paragraphStyle.lineSpacing设置为0,多行时设置为6
如何获取文本的行数?使用CoreText提供的方法去获取行数,代码如下:

//attrStr不用多说,width为约束宽度
- (NSUInteger)getLineCount:(NSAttributedString *)attStr withConstraintWidth:(CGFloat)width{
    CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString(( CFAttributedStringRef)attStr);
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathAddRect(path, NULL, CGRectMake(0,0,width,100000));
    CTFrameRef frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, 0), path, NULL);
    NSArray *lines = ( NSArray *)CTFrameGetLines(frame);
    CGPathRelease(path);
    CFRelease( frame );
    CFRelease(frameSetter);
    return lines.count;
}

行数获取到了,接下来需要设置NSAttributedString的属性。
由于NSAttributedString的属性可能会随着range的不同而不同,所以我们需要遍历所有range的属性然后变换NSMutableParagraphStyle的lineSpacing为0,其他属性保持不变。

通过-[NSAttributedString attributesAtIndex:effectiveRange:]可以遍历所有属性。

参数说明:

  1. attributesAtIndex 为索引
  2. effectiveRange为在attributesAtIndex的位置属性对应的范围,传入的是指针。
//获取行数
NSUInteger lineCount = [self getLineCount:attributedMessage
                      withConstraintWidth:AHAnimationHUDContainerViewMaxWidth];
//一行文字特殊处理 设置行间距为0
if (lineCount == 1) {
    //复制attributedMessage
    NSMutableAttributedString * newAttrString = [[NSMutableAttributedString alloc] initWithAttributedString:attributedMessage];
    NSRange range = NSMakeRange(0, 0);
    //遍历所有属性
    while ((range.location + range.length) < attributedMessage.length) {
        //获取属性
        NSDictionary * attr = [attributedMessage attributesAtIndex:range.location+range.length effectiveRange:&range];
        if (attr) {
            //拷贝属性
            NSMutableDictionary * newAttr = [NSMutableDictionary dictionaryWithDictionary:attr];
            //获取NSParagraphStyle属性
            NSParagraphStyle * pStyle = [newAttr objectForKey:NSParagraphStyleAttributeName];
            if (pStyle) {
                NSMutableParagraphStyle * newPStyle = [[NSMutableParagraphStyle alloc] init];
                //拷贝NSParagraphStyle
                [newPStyle setParagraphStyle:pStyle];
                //设置行间距为0
                newPStyle.lineSpacing = 0;
                //用lineSpacing为0的NSParagraphStyle覆盖旧的NSParagraphStyle
                [newAttr setObject:newPStyle forKey:NSParagraphStyleAttributeName];
                //在对应的range设置属性
                [newAttrString setAttributes:newAttr range:range];
            }
        }
    }
}

以上newAttrString就是将lineSpacing设置为0之后的结果,将该变量赋值给UILabel即可。

You Might Also Like
发表评论