【问题标题】:How to align baselines of text in UILabels with different font sizes on iOS?如何在 iOS 上将 UILabel 中的文本基线与不同的字体大小对齐?
【发布时间】:2012-04-12 05:41:54
【问题描述】:

我需要对齐 UILabel 中文本的基线。我目前正在做的是对齐包含文本的 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 的基线是对齐的,文本的基线也会有一点点未对齐。如何动态对齐文本的基线(因为字体大小可能会在运行时发生变化)?

【问题讨论】:

    标签: iphone ios ios4


    【解决方案1】:

    我在几个不同的地方使用了this answer,但基线有时在 Retina 显示器上相差一个像素。下面的 sn-p 说明了屏幕的比例:

    [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;
    

    【讨论】:

    • 任何使用自动布局的版本?
    • 自动布局版本很简单:只需将两个标签按NSLayoutAttributeBaseline(或NSLayoutAttributeLastBaselineNSLayoutAttributeFirstBaseline,取决于您要做什么)对齐。
    【解决方案2】:

    通过在简单的计算中使用 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 信息),请查看此简洁明了的 article

    【讨论】:

    • 我试过这个,但是,在我对 iOS5 的测试中,升序和降序都是 0
    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

      我想自己做这件事(刚刚),并在almost identical question 上找到了我的答案。但这不是简单的解决方案,我们必须进行数学计算。

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

      【讨论】:

        【解决方案5】:

        使用自动布局,它更容易。 选择要对齐的 2 个标签并转到对齐工具。选择“底边”/“顶边”/基线

        【讨论】:

        • 你的答案是错误的,它们应该与基线对齐,查看其他答案
        猜你喜欢
        • 2018-07-04
        • 2020-09-06
        • 1970-01-01
        • 1970-01-01
        • 2016-05-28
        • 1970-01-01
        • 2021-06-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多