ios 在 UILabel 中垂直对齐文本(注意:使用 AutoLayout)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28605341/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 04:54:30  来源:igfitidea点击:

Vertically align text within a UILabel (Note : Using AutoLayout)

iosobjective-ccocoa-touchautolayoutuilabel

提问by MELWIN

I am Copying the same Question asked Before Question. I have tried the solutions given and was not able to solve it since sizetofitwas not effective when I use Autolayout.

我正在复制在问题之前提出的相同问题。我曾试图给出的解决方案,并没有能够解决它,因为sizetofit当我使用自动布局是无效的。

first screenshot

first screenshot

The expected display is like below.

预期的显示如下。

second screenshot

second screenshot

回答by Daniel Galasko

Edit

编辑

In my original answer I was using the paragraph style of the label. Turns out that for multi-line labels this actually prevents the label from being multi-line. As a result I removed it from the calculation. See more about this in Github

在我的原始答案中,我使用了标签的段落样式。事实证明,对于多行标签,这实际上可以防止标签成为多行。结果我从计算中删除了它。在Github 中查看更多相关信息

For those of you more comfortable with using Open Source definitely look at TTTAttributedLabelwhere you can set the label's text alignment to TTTAttributedLabelVerticalAlignmentTop

对于那些更习惯使用开源的人,请务必查看TTTAttributedLabel,您可以在其中将标签的文本对齐方式设置为TTTAttributedLabelVerticalAlignmentTop



The trick is to subclass UILabeland override drawTextInRect. Then enforce that the text is drawn at the origin of the label's bounds.

诀窍是子类化UILabel和覆盖drawTextInRect. 然后强制在标签边界的原点绘制文本。

Here's a naive implementation that you can use right now:

这是您现在可以使用的简单实现:

Swift

迅速

@IBDesignable class TopAlignedLabel: UILabel {
    override func drawTextInRect(rect: CGRect) {
        if let stringText = text {
            let stringTextAsNSString = stringText as NSString
            var labelStringSize = stringTextAsNSString.boundingRectWithSize(CGSizeMake(CGRectGetWidth(self.frame), CGFloat.max),
                options: NSStringDrawingOptions.UsesLineFragmentOrigin,
                attributes: [NSFontAttributeName: font],
                context: nil).size
            super.drawTextInRect(CGRectMake(0, 0, CGRectGetWidth(self.frame), ceil(labelStringSize.height)))
        } else {
            super.drawTextInRect(rect)
        }
    }
    override func prepareForInterfaceBuilder() {
        super.prepareForInterfaceBuilder()
        layer.borderWidth = 1
        layer.borderColor = UIColor.blackColor().CGColor
    }
}

Swift 3

斯威夫特 3

  @IBDesignable class TopAlignedLabel: UILabel {
    override func drawText(in rect: CGRect) {
        if let stringText = text {
            let stringTextAsNSString = stringText as NSString
            let labelStringSize = stringTextAsNSString.boundingRect(with: CGSize(width: self.frame.width,height: CGFloat.greatestFiniteMagnitude),
                                                                            options: NSStringDrawingOptions.usesLineFragmentOrigin,
                                                                            attributes: [NSFontAttributeName: font],
                                                                            context: nil).size
            super.drawText(in: CGRect(x:0,y: 0,width: self.frame.width, height:ceil(labelStringSize.height)))
        } else {
            super.drawText(in: rect)
        }
    }
    override func prepareForInterfaceBuilder() {
        super.prepareForInterfaceBuilder()
        layer.borderWidth = 1
        layer.borderColor = UIColor.black.cgColor
    }
}

Objective-C

目标-C

IB_DESIGNABLE
@interface TopAlignedLabel : UILabel

@end

@implementation TopAlignedLabel

- (void)drawTextInRect:(CGRect)rect {
    if (self.text) {
        CGSize labelStringSize = [self.text boundingRectWithSize:CGSizeMake(CGRectGetWidth(self.frame), CGFLOAT_MAX)
                                                         options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
                                                      attributes:@{NSFontAttributeName:self.font}
                                                         context:nil].size;
        [super drawTextInRect:CGRectMake(0, 0, ceilf(CGRectGetWidth(self.frame)),ceilf(labelStringSize.height))];
    } else {
        [super drawTextInRect:rect];
    }
}

- (void)prepareForInterfaceBuilder {
        [super prepareForInterfaceBuilder];
        self.layer.borderWidth = 1;
        self.layer.borderColor = [UIColor blackColor].CGColor;
}

@end


Since I used IBDesignable you can add this label to a storyboard and watch it go, this is what it looks like for me

由于我使用了 IBDesignable,您可以将此标签添加到故事板并观看它,这就是我的样子

enter image description here

enter image description here

回答by Nikola Milicevic

If you're not restricted by having UILabel of fixed size, instead of aligning the text within a UILabel, simply use ≥ constraint on the given label to change the size of it.

如果您不受 UILabel 固定大小的限制,而不是在 UILabel 内对齐文本,只需在给定标签上使用 ≥ 约束来更改其大小。

enter image description here

enter image description here

It's the most elegant solution using Auto Layout. Don't forget to set numberOfLinesto zero though.

这是使用自动布局的最优雅的解决方案。不要忘记将numberOfLines设置为零。

回答by arturdev

You can use UITextView instead of UILabel:
Uncheck "Scrolling enabled"
Uncheck "Editable"
Uncheck "Selectable"
Set background color to ClearColor

您可以使用 UITextView 而不是 UILabel:
取消选中“启用滚动”
取消选中“可编辑”
取消选中“可选”
将背景颜色设置为 ClearColor

回答by Oyvkva

I had the same problem, and this is how I solved it. I just edited the Baseline under Attribute Inspector for the Label. Set it to "Align Centers".

我遇到了同样的问题,这就是我解决它的方法。我刚刚在标签的属性检查器下编辑了基线。将其设置为“对齐中心”。

Setting baseline to Align Centers

Setting baseline to Align Centers

回答by Felipe FMMobile

Instead, I changed the Bottom Space Constant to priority @250 and solved my problem. And my label has height constant with <= constant

相反,我将底部空间常数更改为优先级 @250 并解决了我的问题。我的标签具有 <= 常量的高度常量

回答by Wain

You would do that by removing the minimum height.

您可以通过删除最小高度来做到这一点。

If you need the minimum height to something else below the label then you would use a container view that resized based on the label contents but used a minimum.

如果您需要标签下方其他东西的最小高度,那么您将使用根据标签内容调整大小但使用最小值的容器视图。

回答by ezchen

I used @Daniel Golasko's solution and whenever the text inside the UILabel was longer than the UILabel could contain, the text would start moving down instead of staying aligned to top.

我使用了@Daniel Golasko 的解决方案,每当 UILabel 中的文本长于 UILabel 可以包含的长度时,文本就会开始向下移动而不是保持与顶部对齐。

I changed this line to make sure the text is aligned properly

我更改了这一行以确保文本正确对齐

    [super drawTextInRect:CGRectMake(0, 0, ceilf(CGRectGetWidth(self.frame)),MIN(ceilf(labelStringSize.height), self.frame.size.height))];

回答by P?tur Magnussen

I had a similiar issue where there were 3 labels. The middle label could have much longer text than the other two, so its height could grow much larger.

我有一个类似的问题,有 3 个标签。中间标签的文本可能比其他两个标签长得多,因此它的高度可以变得更大。

Like this:

像这样:

enter image description here

enter image description here

I set the middle label's bottom space constraint to be >= the bottom label.

我将中间标签的底部空间约束设置为 >= 底部标签。

enter image description here

enter image description here

That solved my problem.

那解决了我的问题。

回答by Alexander Poleschuk

There is an easy solution for cases where the height of a label doesn't need to be constant: put your Labelin a Stack View. Be sure to add leading and trailing constants to the Stack View. Here is a screenshot of how to do it in storyboard:

对于标签高度不需要恒定的情况,有一个简单的解决方案:将您LabelStack View. 确保将前导和尾随常量添加到Stack View. 这是如何在故事板中执行此操作的屏幕截图:

enter image description here

enter image description here

回答by dimpiax

Swift 4

斯威夫特 4

You should subclass UILabel and override text display rendering.

您应该继承 UILabel 并覆盖文本显示渲染。

class UITopAlignedLabel: UILabel {
    override func drawText(in rect: CGRect) {
        guard let string = text else {
            super.drawText(in: rect)
            return
        }

        let size = (string as NSString).boundingRect(
            with: CGSize(width: rect.width, height: .greatestFiniteMagnitude),
            options: [.usesLineFragmentOrigin],
            attributes: [.font: font],
            context: nil).size

        var rect = rect
        rect.size.height = size.height.rounded()
        super.drawText(in: rect)
    }
}