如何在iOS上将UILabels中的文本基线与不同的字体大小对齐?

我需要在UILabels中对齐文本的基线。 我目前正在做的是我正在调整包含文本的UILabels的基线,当两个标签中的文本字体大小不同时,这会导致UILabels基线对齐但文本基线未对齐(未对齐不足,但仍然错位)。 标签包含在自定义UIView子类中,因此self指的是包含UIView。

这是相关的代码

 [self.mySmallLabel sizeToFit]; [self.myBigLabel sizeToFit]; self.mySmallLabel.frame = CGRectMake(0, self.bounds.size.height - self.mySmallLabel.bounds.size.height, self.mySmallLabel.bounds.size.width, self.mySmallLabel.bounds.size.height); self.myBigLabel.frame = CGRectMake(self.mySmallLabel.frame.origin.x + self.mySmallLabel.bounds.size.width, self.bounds.size.height - self.myBigLabel.bounds.size.height, self.myBigLabel.bounds.size.width, self.myBigLabel.bounds.size.height); [self.mySmallLabel sizeToFit]; [self.myBigLabel sizeToFit]; 

此代码导致下面链接的图像中的对齐。

Misalignemnt

如您所见,即使UILabel基线对齐,文本的基线也会略微偏移。 如何动态对齐文本的基线(因为字体大小可能会在运行时更改)?

我在几个不同的地方使用这个答案 ,但基线有时是Retina显示屏上的一个像素。 下面的代码片段说明了屏幕的比例:

 [majorLabel sizeToFit]; [minorLabel sizeToFit]; CGRect changedFrame = minorLabel.frame; changedFrame.origin.x = CGRectGetWidth(majorLabel.frame); const CGFloat scale = [UIScreen mainScreen].scale; const CGFloat majorLabelBaselineInSuperView = CGRectGetMaxY(majorLabel.frame) + majorLabel.font.descender; const CGFloat minorLabelBaselineInOwnView = CGRectGetHeight(minorLabel.frame) + minorLabel.font.descender; changedFrame.origin.y = ceil((majorLabelBaselineInSuperView - minorLabelBaselineInOwnView) * scale) / scale; minorLabel.frame = changedFrame; 

通过在简单计算中使用UIFont ascender值,您可以为任何一对UILabel获得像素完美的基线对齐。 就是这样:

 [majorLabel sizeToFit]; [minorLabel sizeToFit]; CGRect changedFrame = minorLabel.frame; changedFrame.origin.y = ceilf(majorLabel.frame.origin.y + (majorLabel.font.ascender - minorLabel.font.ascender)); minorLabel.frame = changedFrame; 

ceilf()是因为font.ascender值可能是小数。

我已经在视网膜和非视网膜设备上进行了测试,结果非常好。 由于您的需求可能会有所不同,因此省略了将两个标签相对于彼此放置在x轴上。 如果您需要快速解释UIFont ascender是什么(以及其他UIFont信息),请查看这篇简明扼要的文章 。

我本人希望自己(刚才)这样做,并在一个几乎相同的问题上找到答案。 这不是简单的解决方案,我们必须做数学。

我只需要用2个不同的标签来做,我在UIView的子类中做。

 - (void)layoutSubviews { [majorLabel sizeToFit]; [minorLabel sizeToFit]; CGRect changedFrame = minorLabel.frame; changedFrame.origin.x = majorLabel.frame.size.width; changedFrame.origin.y = (majorLabel.frame.size.height + majorLabel.font.descender) - (minorLabel.frame.size.height + minorLabel.font.descender); minorLabel.frame = changedFrame; } 

iOS9之后。 使用autolayout,UILabel有一个名为: lastBaselineAnchor的锚。 例如:

 hintLabel.lastBaselineAnchor.constraint(equalTo: titleLabel.lastBaselineAnchor).isActive = true