Label设置行间距

Label设置行间距

内容摘要

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

场景描述

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

问题分析

Label显示多行文本

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

  • 如果想添加行间距,你可能会这样做:
  • 写一个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;
}
  • 赋值富文本属性

    NSString *string = @"众所周知,UILabel显示多行的话,默认行间距为0,但实际开发中,如果显示多行文本,一般情况下会有一定的行间距。如果想动态调整行间距,则需要赋值**富文本属性**(而不是文本属性)";
    // 5:行间距
    self.lblResult.attributedText = [self getAttributedStringWithString:string lineSpace:5];
  • 结果如下图:

    =============== 华丽的分割线 ===============

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

  • Label显示单行文本

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

    * 显示单行英文:

    NSString *string = @"good good study day day up";
    self.lblResult.attributedText = [self getAttributedStringWithString:string lineSpace:5];

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

    遇到问题之后

    • 查询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;
    • 各种尝试之后,问题还在那儿……
    • 想到富文本属性,查询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

    尝试解决问题

    • 重构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;
    }
    • 于是单行文本显示成这样:

    • 那么多行呢?

      我擦!

    问题分析

    • 通过上面的示例分析,可以简单的得到结论:

      • 未设置行间距和偏移量,什么问题都没有,只是行与行之间显示得比较紧促!
      • 只设置行间距,多行和单行英文情况下,显示没有问题,但单行中文显示会有问题,底部会有空白!
      • 既设置行间距,也设置偏移的情况下,单行显示没有问题,但多行显示有问题!

    解决办法

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

    那么问题来了,如何判断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];
    • 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];
    • 画线
    // 画线
    -(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 . . .]

    时间: 2024-10-09 22:13:41

    Label设置行间距的相关文章

    Label设置行间距--b

    内容摘要 UILabel显示多行文本 UILabel设置行间距 解决单行文本 & 多行文本显示的问题 场景描述 众所周知,UILabel显示多行的话,默认行间距为0,但实际开发中,如果显示多行文本,一般情况下会有一定的行间距.如果想动态调整行间距,则需要赋值富文本属性(而不是文本属性) 问题分析 Label显示多行文本 label默认情况下,只会显示单行文本,主要是因为它的numberOfLines属性值是1:如果要显示多行,把这个属性值改成0即可. self.lblResult.numberO

    label 设置行间距 字间距

    #import "MyLabel.h" #import <CoreText/CoreText.h> @implementation MyLabel +(void)setLabel:(UILabel *)custonLabel andContenStr:(NSString *)content andlineSpace:(CGFloat)lineSpace andHeightSpace:(long)fontSpace{ NSMutableAttributedString *st

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

    一,效果图. 二,代码. RootViewController.m - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. //UILabel UILabel *label=[[UILabel alloc]initWithFrame:CGRectMake(50, 100, 200, 300)]; label.backgroundColor=[UIColor oran

    【代码笔记】设置textView或者label的行间距方法

    一,效果图. 二,代码. RootViewController.m - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. //UILabel UILabel *label=[[UILabel alloc]initWithFrame:CGRectMake(50, 100, 200, 300)]; label.backgroundColor=[UIColor oran

    UILabel设置行间距和字间距并计算高度-b

    #define UILABEL_LINE_SPACE 6 #define HEIGHT [ [ UIScreen mainScreen ] bounds ].size.height //给UILabel设置行间距和字间距 -(void)setLabelSpace:(UILabel*)label withValue:(NSString*)str withFont:(UIFont*)font { NSMutableParagraphStyle *paraStyle = [[NSMutablePara

    QLabel设置行间距(使用html的语法,比较巧妙)

    1.设置行间距 QLabel没有设置行间距的函数,所以这种办法是行不通的.只能采用其它类似的方法来实现,例如设置行高,使用样式代码如下: <p style='line-height:18px'>推荐</p> 2.链接文本 实现点击Label,即可打开网页,且文本没有下划线效果,如下: <a href="http://www.sina.com"><span style="text-decoration: none; color:#ff0

    Android TextView 设置行间距的问题 (setLineSpacing ,lineSpacingExtra, lineSpacingMultiplier)

    最近的项目中,需要用到自定义控件.有个组件要获取绘制文本的高度,翻开TextView 的源码,有个方法 getLineHeight() public int getLineHeight() { return FastMath.round(mTextPaint.getFontMetricsInt(null) * mSpacingMult + mSpacingAdd); } getLineHeight 的注释如下: /** * @return the height of one standard l

    使用CSS设置行间距,字间距

    原链接:http://blog.sina.com.cn/s/blog_a03d702f01013u3q.html 字间距1.text-indent设置抬头距离css缩进即对,对应div设置css样式text-indent : 20px; 缩进了20px 2.letter-spacing来设置字与字间距_字符间距离,字体间距css样式即对对应div设置css属性样式为letter-spacing:8px;,字间距为8px 行间距 在CSS中,可以设置行间距,格式如下:标签名{line-height

    UILabel设置行间距

    UILabel设置行间距: NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc]initWithString:contentLabel.text]; NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStylealloc]init]; [paragraphStyle setLineSpacing:5]; [attri