UILabel linespacing issue when text is singleline

问题背景:

项目中经常需要给UILabel设置linespacing,但是在使用的过程中我们发现当我们设置linespacing,[label sizeToFit]后的高度会多出一个linespacing,严重影响布局

分析:

影响因素有很多:

  • font
  • UILabel.numberOfLines
  • paragraphStyle.lineBreakMode
  • UILabel.width
  • UILabel.text

这些变量的可能取值有:

systemFontOfSize

显式指定字体

单行(1)

有限制的多行(>1)

不限制行数(0)

NSLineBreakByTruncatingTail

NSLineBreakByCharWrapping

小于文本总宽度

大于等于文本总宽度

纯英文字符串

包含非英文字符串(中文,日文)

解决方法:

给label显式地指定字体

UIFont *titleFont = [UIFont fontWithName:@“PingFangSC-Regular” size:14];

不要使用

UIFont *titleFont = [UIFont systemFontOfSize:14];

 

参考链接:

http://stackoverflow.com/questions/32291105/line-spacing-for-uilabel-with-a-single-line-of-text

新的问题:

虽然上面的解决方法,使得[label sizeToFit]后的高度是准确的,无论numberOfLines是多少。但是我们经常需要给label一个最大宽度,那么问题来了。 当我们给label限制了最大宽度,且label.numberOfLines=1,此时如果label.text内容比较多,在限制的宽度下显示不完整,就会出现label渲染的时候没有垂直居中渲染文字,而是贴着label的顶部,底部留下间隙。如果在限制的宽度下,能显示完,也不存在这个问题

经过尝试,发现:

  1. paragraphStyle.lineBreakMode = NSLineBreakByCharWrapping;不存在这个问题,
  2. paragraphStyle.lineBreakMode = NSLineBreakByTruncatingTail;有这个问题。

如果lineBreakMode = NSLineBreakByCharWrapping,就不会出现文本末尾“…”,视觉和产品可能不接受。。。

 

下面是实验对比截图:

页面中有两个UILabel实例,第一个label的numberOfLines=1,第二个label的numberOfLines=0。

 

图1. 未做任何处理,使用系统字体,sizeToFit的结果。多行的时候表现正常,一行的时候高度多了一个linespacing

Simulator Screen Shot 2016年7月14日 上午10.40.20

图2.  显式指定字体为苹方字体,sizeToFit后,表现都正常。Simulator Screen Shot 2016年7月14日 上午10.54.33

图3. 显式指定字体为苹方字体

UIFont *titleFont = [UIFont fontWithName:@”PingFangSC-Regular” size:14];

,sizeToFit后,label 的高度都是计算正确的,只不过,当我们再修改label.numberOfLines=1的label的width为比较小的值,出现渲染问题。

Simulator Screen Shot 2016年7月14日 上午11.13.51 

总结:

 

  1. 当我们已经从需求来源明确了label的numberOfLines=1,不能给label设置linespacing
  2. 当我们确定label的numberOfLines 不为1,如果需要给label设置linespacing的话,请一定要显式的给它设置字体,不要使用[UIFont systemFontOfSize:14]这种方式给它设置字体,其实就是给attributedText设置字体。