Label设置行间距--b

Posted qigemingnan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Label设置行间距--b相关的知识,希望对你有一定的参考价值。

内容摘要

  • UILabel显示多行文本
  • UILabel设置行间距
  • 解决单行文本 & 多行文本显示的问题

场景描述

  • 众所周知,UILabel显示多行的话,默认行间距为0,但实际开发中,如果显示多行文本,一般情况下会有一定的行间距。如果想动态调整行间距,则需要赋值富文本属性(而不是文本属性

问题分析

Label显示多行文本

  • label默认情况下,只会显示单行文本,主要是因为它的numberOfLines属性值是1;如果要显示多行,把这个属性值改成0即可。
self.lblResult.numberOfLines = 0;
  • 1
  • 1

 


  • 默认情况下,会显示成这样: 
    技术分享
  • 如果想添加行间距,你可能会这样做:

 

  • 写一个string转换成AttributedString的方法(或者给字符串增加一个分类)
-(NSAttributedString *)getAttributedStringWithString:(NSString *)string lineSpace:(CGFloat)lineSpace {
    NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:string];
    NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
    paragraphStyle.lineSpacing = lineSpace; // 调整行间距
    NSRange range = NSMakeRange(0, [string length]);
    [attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:range];
    return attributedString;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 赋值富文本属性 
    NSString *string = @"众所周知,UILabel显示多行的话,默认行间距为0,但实际开发中,如果显示多行文本,一般情况下会有一定的行间距。如果想动态调整行间距,则需要赋值**富文本属性**(而不是文本属性)";
    // 5:行间距
    self.lblResult.attributedText = [self getAttributedStringWithString:string lineSpace:5];
    • 1
    • 2
    • 3
    • 1
    • 2
    • 3
  • 结果如下图: 
    技术分享 
    =============== 华丽的分割线 =============== 

    问题:以上方法显示多行文本貌似没有问题,但如果文本只有一行呢?

Label显示单行文本

  • 显示单行中文:
NSString *string = @"文本只有一行会显示什么样?";
self.lblResult.attributedText = [self getAttributedStringWithString:string lineSpace:5];
  • 1
  • 2
  • 1
  • 2

技术分享

  • 显示单行英文:
NSString *string = @"good good study day day up";
self.lblResult.attributedText = [self getAttributedStringWithString:string lineSpace:5];
  • 1
  • 2
  • 1
  • 2

技术分享

  • 通过比较发现,用同样的方法,单行显示中文 & 英文,效果不同,中文会多了一些空白!心中立马有种蛋蛋的忧桑,一丝丝凄凉……

遇到问题之后

  • 查询API-NSMutableParagraphStyle

    // Indent:缩进
    @property(NS_NONATOMIC_iosONLY) CGFloat lineSpacing;
    @property(NS_NONATOMIC_IOSONLY) CGFloat paragraphSpacing;
    @property(NS_NONATOMIC_IOSONLY) NSTextAlignment alignment;
    @property(NS_NONATOMIC_IOSONLY) CGFloat firstLineHeadIndent;
    @property(NS_NONATOMIC_IOSONLY) CGFloat headIndent;
    @property(NS_NONATOMIC_IOSONLY) CGFloat tailIndent;
    @property(NS_NONATOMIC_IOSONLY) NSLineBreakMode lineBreakMode;
    @property(NS_NONATOMIC_IOSONLY) CGFloat minimumLineHeight;
    @property(NS_NONATOMIC_IOSONLY) CGFloat maximumLineHeight;
    @property(NS_NONATOMIC_IOSONLY) NSWritingDirection baseWritingDirection;
    @property(NS_NONATOMIC_IOSONLY) CGFloat lineHeightMultiple;
    @property(NS_NONATOMIC_IOSONLY) CGFloat paragraphSpacingBefore;
    @property(NS_NONATOMIC_IOSONLY) float hyphenationFactor;
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
  • 各种尝试之后,问题还在那儿……
  • 想到富文本属性,查询NSAttributedString.h头文件

    • 仿佛看到了胜利的曙光
    UIKIT_EXTERN NSString * const NSBaselineOffsetAttributeName NS_AVAILABLE(10_0, 7_0);      // NSNumber containing floating point value, in points; offset from baseline, default 0
    • 1
    • 1

尝试解决问题

  • 重构getAttributedStringWithString方法
-(NSAttributedString *)getAttributedStringWithString:(NSString *)string lineSpace:(CGFloat)lineSpace baselineOffset:(CGFloat)baselineOffset {
    NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:string];
    NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
    paragraphStyle.lineSpacing = lineSpace; // 调整行间距
    NSRange range = NSMakeRange(0, [string length]);
    [attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:range];
    // 设置文本偏移量
    [attributedString addAttribute:NSBaselineOffsetAttributeName value:@(baselineOffset) range:range];
    return attributedString;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 于是单行文本显示成这样: 
    技术分享 
    技术分享

  • 那么多行呢? 
    技术分享 
    技术分享

我擦!

问题分析

  • 通过上面的示例分析,可以简单的得到结论: 
    • 未设置行间距和偏移量,什么问题都没有,只是行与行之间显示得比较紧促!
    • 只设置行间距,多行和单行英文情况下,显示没有问题,但单行中文显示会有问题,底部会有空白!
    • 既设置行间距,也设置偏移的情况下,单行显示没有问题,但多行显示有问题!

解决办法

  • 多行情况下,不设置偏移!

那么问题来了,如何判断label显示几行呢?

  • 笔者用比较笨的方法:计算某几个固定字符的高度,然后再计算label文本的高度,如果后者大于前者,则为多行!
  • 示例代码如下:
CGFloat lineSpace = 5;
CGFloat offset = -(1.0/3 * lineSpace) - 1.0/3;
CGFloat marginLeft = 20;
CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width;
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineSpacing = lineSpace; // 调整行间距
NSDictionary *attrs = @{
                            NSFontAttributeName : self.lblResult.font,
                            NSParagraphStyleAttributeName : paragraphStyle
                            };
// 计算一行文本的高度
CGFloat oneHeight = [@"测试Test" boundingRectWithSize:CGSizeMake(screenWidth-marginLeft*2, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:attrs context:nil].size.height;
CGFloat rowHeight = [self.txtInputString.text boundingRectWithSize:CGSizeMake(screenWidth-marginLeft*2, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:attrs context:nil].size.height;
// 如果超出一行,则offset=0;
offset = rowHeight > oneHeight ? 0 : offset;
self.lblResult.attributedText = [self getAttributedStringWithString:self.txtInputString.text lineSpace:lineSpace baselineOffset:offset];
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • OK,这样貌似解决了上面的问题,但细心的你估计会发现一个问题:CGFloat offset = -(1.0/3 * lineSpace) - 1.0/3;这行代码是什么意思?

关于 f(x) = -(1.0/3 * x) - 1.0/3

  • offset是通过穷举法归纳总结出来的,也许不够准确,但在项目中用起来挺好。
  • 根据文本内容,描点
// 描点
CGPoint points[15];
// CGPointMake(lineSpace, offset)
points[0] = CGPointMake(5, -2);
points[1] = CGPointMake(8, -3);
points[2] = CGPointMake(10, -3.5);
points[3] = CGPointMake(16, -6);
points[4] = CGPointMake(20, -7);
points[5] = CGPointMake(25, -9);
points[6] = CGPointMake(30, -11);
points[7] = CGPointMake(35, -11.5);
points[8] = CGPointMake(40, -13);
points[9] = CGPointMake(50, -15);
points[10] = CGPointMake(60, -18.5);
points[11] = CGPointMake(70, -23);
points[12] = CGPointMake(80, -26);
points[13] = CGPointMake(90, -29);
points[14] = CGPointMake(100, -32);
// 画线
[self drawLine:points count:15];
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 画线
// 画线
-(void)drawLine:(CGPoint[])points count:(NSInteger)count {
    CGMutablePathRef linePath = CGPathCreateMutable();
    CGPathAddLines(linePath, NULL, points, count);
    // 关联layer和贝塞尔路径
    self.linesLayer.path = linePath;
    CGPathRelease(linePath);
    // 创建Animation
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
    animation.fromValue = @(0.0);
    animation.toValue = @(1.0);
    self.linesLayer.autoreverses = NO;
    animation.duration = 1.5f;
    // 设置layer的animation
    [self.linesLayer addAnimation:animation forKey:nil];
    self.linesLayer.strokeEnd = 1;
}
![Uploading Label设置行间距_归纳总结offset的算法_323780.png . . .]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

技术分享

 
http://blog.csdn.net/chenyblog/article/details/51172776  是原文地址   感谢分享 

以上是关于Label设置行间距--b的主要内容,如果未能解决你的问题,请参考以下文章

设置textView或者label的行间距方法

设置textView或者label的行间距方法

NSMutableAttributedString怎么设置label的行间距

iOS 设置Label的行间距

label_设置行距字距及计算含有行间距的label高度

iOS中文行间距富文本高度与显示那些坑