繁体   English   中英

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

[英]How to align baselines of text in UILabels with different font sizes on iOS?

我需要对齐 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];

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

错位

如您所见,即使 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 上升值,您可以为任何一对 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 上升器是什么(以及其他 UIFont 信息),请查看这篇清晰简洁的文章

iOS9之后。 使用自动布局,UILabel 有一个名为: lastBaselineAnchor的锚点。 例如:

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

我想自己做这件事(刚才),并在一个几乎相同的问题上找到了我的答案。 但这不是简单的解决方案,我们必须进行数学计算。

我只需要用 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;
}

使用自动布局,它更容易。 选择要对齐的 2 个标签并转到“对齐”工具。 选择“底边”/“顶边”/基线在此处输入图片说明

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM