如何在 iOS 上将 UILabels 中文本的基线与不同的字体大小对齐?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9910766/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to align baselines of text in UILabels with different font sizes on iOS?
提问by akaralar
I need to align the baselines of text in UILabels. What I'm currently doing is I'm aligning the baselines of UILabels containing the text, and when the text font size in two labels is different, this results in aligned UILabels baseline but misaligned text baseline (misaligned by a small margin, but still misaligned). The labels are included in a custom UIView subclass, therefore self
refers to the encompassing UIView.
我需要对齐 UILabels 中文本的基线。我目前正在做的是对齐包含文本的 UILabels 的基线,并且当两个标签中的文本字体大小不同时,这会导致对齐的 UILabels 基线但未对齐的文本基线(未对齐很小的边距,但仍然错位)。标签包含在自定义 UIView 子类中,因此self
是指包含的 UIView。
here is the relevant code
这是相关的代码
[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];
This code results in the aligment in the image linked below.
此代码导致下面链接的图像中的对齐。
As you can see, even though the UILabel baselines are aligned, the baselines of the text is misaligned by a small margin. How can I align the baselines of text dynamically (because font sizes might change at runtime)?
如您所见,即使 UILabel 基线对齐,文本的基线也有一小部分未对齐。如何动态对齐文本的基线(因为字体大小可能会在运行时改变)?
回答by eager
I was using this answerin a couple of different places, but the baselines were sometimes a pixel off on Retina displays. The snippet below accounts for the screen's scale:
我在几个不同的地方使用了这个答案,但基线有时在 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;
回答by John Jacecko
You can get pixel-perfect baseline alignment for any pair of UILabels by using the UIFont ascender value in a simple calculation. Here's how:
通过在简单的计算中使用 UIFont 上升值,您可以为任何一对 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()
is used because the font.ascender values may be fractional.
ceilf()
之所以使用,是因为 font.ascender 值可能是小数。
I've tested this on both retina and non-retina devices, with excellent results. Positioning the two labels relative to each other on the x-axis has been omitted, as your needs may vary. If you need a quick explanation of what the UIFont ascender is (plus other UIFont info) check out this clear, concise article.
我已经在视网膜和非视网膜设备上对此进行了测试,结果非常好。由于您的需求可能会有所不同,因此省略了在 x 轴上相对于彼此的两个标签的定位。如果您需要快速解释 UIFont 上升器是什么(以及其他 UIFont 信息),请查看这篇清晰简洁的文章。
回答by DBD
I was looking to do this myself (just now) and found my answer on an almost identical question. It's not simple solution though, we have to do the math.
我想自己做这件事(刚才),并在一个几乎相同的问题上找到了我的答案。但这不是简单的解决方案,我们必须进行数学计算。
I only needed to do it with 2 different labels and I'm doing it in a subclass of UIView
.
我只需要用 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;
}
回答by boog
After iOS9. With autolayout, UILabel has an anchor called: lastBaselineAnchor. For example:
在iOS9之后。使用自动布局,UILabel 有一个名为:lastBaselineAnchor的锚点。例如:
hintLabel.lastBaselineAnchor.constraint(equalTo: titleLabel.lastBaselineAnchor).isActive = true