问:

我有一个带有两行文本空间的 UILabel。有时,当文本太短时,该文本会显示在标签的垂直中心。

如何垂直对齐文本以始终位于 UILabel 的顶部?

答1:

huntsbot.com提供全网独家一站式外包任务、远程工作、创意产品分享与订阅服务!

无法在 UILabel 上设置垂直对齐,但您可以通过更改标签的框架来获得相同的效果。我已将标签设为橙色,以便您清楚地看到正在发生的事情。

这是执行此操作的快速简便的方法:

[myLabel sizeToFit];

如果您有一个包含超过一行的较长文本的标签,请将 numberOfLines 设置为 0(此处的零表示行数不受限制)。

myLabel.numberOfLines = 0;
    [myLabel sizeToFit];

更长的版本

我将在代码中制作我的标签,以便您可以看到发生了什么。您也可以在 Interface Builder 中设置大部分内容。我的设置是一个基于视图的应用程序,带有我在 Photoshop 中制作的背景图像以显示边距(20 点)。标签是迷人的橙色,因此您可以看到尺寸的变化。

- (void)viewDidLoad
{
    [super viewDidLoad];

    // 20 point top and left margin. Sized to leave 20 pt at right.
    CGRect labelFrame = CGRectMake(20, 20, 280, 150);
    UILabel *myLabel = [[UILabel alloc] initWithFrame:labelFrame];
    [myLabel setBackgroundColor:[UIColor orangeColor]];

    NSString *labelText = @"I am the very model of a modern Major-General, I've information vegetable, animal, and mineral";
    [myLabel setText:labelText];

    // Tell the label to use an unlimited number of lines
    [myLabel setNumberOfLines:0];
    [myLabel sizeToFit];

    [self.view addSubview:myLabel];
}

使用 sizeToFit 的一些限制对居中或右对齐的文本起作用。这是发生的事情:

// myLabel.textAlignment = NSTextAlignmentRight;
    myLabel.textAlignment = NSTextAlignmentCenter;

    [myLabel setNumberOfLines:0];
    [myLabel sizeToFit];

https://i.stack.imgur.com/DH18q.png

标签的大小仍为固定的左上角。您可以将原始标签的宽度保存在变量中并在 sizeToFit 之后设置它,或者给它一个固定宽度来解决这些问题:

myLabel.textAlignment = NSTextAlignmentCenter;

    [myLabel setNumberOfLines:0];
    [myLabel sizeToFit];

    CGRect myFrame = myLabel.frame;
    // Resize the frame's width to 280 (320 - margins)
    // width could also be myOriginalLabelFrame.size.width
    myFrame = CGRectMake(myFrame.origin.x, myFrame.origin.y, 280, myFrame.size.height);
    myLabel.frame = myFrame;

https://i.stack.imgur.com/gedYP.png

请注意,sizeToFit 将遵循您的初始标签的最小宽度。如果您从一个 100 宽的标签开始并在其上调用 sizeToFit,它将返回一个(可能非常高)宽度为 100(或更小)的标签。您可能希望在调整大小之前将标签设置为所需的最小宽度。

其他一些需要注意的事项:

是否尊重 lineBreakMode 取决于它的设置方式。 NSLineBreakByTruncatingTail(默认值)在 sizeToFit 之后被忽略,其他两种截断模式(头部和中间)也是如此。 NSLineBreakByClipping 也被忽略。 NSLineBreakByCharWrapping 照常工作。框架宽度仍然变窄以适合最右边的字母。

Mark Amery 在评论中对使用自动布局的 NIB 和 Storyboard 进行了修复:

如果您的标签包含在笔尖或情节提要中作为使用自动布局的 ViewController 的视图的子视图,那么将 sizeToFit 调用放入 viewDidLoad 将不起作用,因为在调用 viewDidLoad 后自动布局大小和位置子视图并将立即撤消您的 sizeToFit 调用的效果。但是,从 viewDidLayoutSubviews 中调用 sizeToFit 将起作用。

我的原始答案(供后代/参考):

这使用 NSString 方法 sizeWithFont:constrainedToSize:lineBreakMode: 计算适合字符串所需的帧高度,然后设置原点和宽度。

使用要插入的文本调整标签框架的大小。这样您就可以容纳任意数量的行。

CGSize maximumSize = CGSizeMake(300, 9999);
NSString *dateString = @"The date today is January 1st, 1999";
UIFont *dateFont = [UIFont fontWithName:@"Helvetica" size:14];
CGSize dateStringSize = [dateString sizeWithFont:dateFont 
        constrainedToSize:maximumSize 
        lineBreakMode:self.dateLabel.lineBreakMode];

CGRect dateFrame = CGRectMake(10, 10, 300, dateStringSize.height);

self.dateLabel.frame = dateFrame;

你需要删除自动布局

这是解决问题的简单方法:stackoverflow.com/a/26632490/636559

这个答案不必要地复杂,它使用了“周围的词”。请参阅下面关于简单更改垂直内容拥抱优先级的建议。不需要任何代码...

[myLabel sizeToFit] 在 UITableViewCells 中不好用,因为这里的标签被重复使用,新文本可能不适合。

您仍然可以使用 AutoLayout 和约束,但要确保 [height] 不会被固定。例如:设置 Left、Top 和 Right 等于 8px,但 Bottom 可以设置“大于或等于”8px。它会对 iOS 说,让我的 sizeToFit 为我的标签决定更好的高度。

答2:

huntsbot.com高效搞钱,一站式跟进超10+任务平台外包需求

设置新文本:myLabel.text = @“Some Text” 将最大行数设置为 0(自动):myLabel.numberOfLines = 0 将标签的框架设置为最大尺寸:myLabel.frame = CGRectMake(20, 20,200,800) 调用 sizeToFit 以减小帧大小,使内容刚好适合:[myLabel sizeToFit]

标签框现在的高度和宽度足以容纳您的文本。左上角应该保持不变。我只用左上对齐的文本对此进行了测试。对于其他对齐方式,您可能必须在之后修改框架。

另外,我的标签启用了自动换行。

这对我来说很好。我在 IB 中设置了我的 UILabel 的尺寸并将 numberOfLines 更改为 0,然后在设置了名为 [myLabel sizeToFit] 的文本之后。

在设置 Attr 中的行数后,对我来说非常适合。督察

在行数超过 1 的情况下不起作用

当您想要两行标签时它不起作用,但文本需要更多行。

答3:

huntsbot.com – 高效赚钱,自由工作

参考扩展解决方案:

for(int i=1; i< newLinesToPad; i++) 
    self.text = [self.text stringByAppendingString:@"\n"];

应该替换为

for(int i=0; iUILabels 的尾随回车似乎被忽略了:(

 同样,alignBottom 也应该用 @" \n@%" 代替 "\n@%" 进行更新(循环初始化也必须由“for(int i=0...”) 替换。

 以下扩展对我有用:

 

```java
// -- file: UILabel+VerticalAlign.h
#pragma mark VerticalAlign
@interface UILabel (VerticalAlign)
- (void)alignTop;
- (void)alignBottom;
@end

// -- file: UILabel+VerticalAlign.m
@implementation UILabel (VerticalAlign)
- (void)alignTop {
    CGSize fontSize = [self.text sizeWithFont:self.font];
    double finalHeight = fontSize.height * self.numberOfLines;
    double finalWidth = self.frame.size.width;    //expected width of label
    CGSize theStringSize = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(finalWidth, finalHeight) lineBreakMode:self.lineBreakMode];
    int newLinesToPad = (finalHeight  - theStringSize.height) / fontSize.height;
    for(int i=0; i[yourLabel alignTop]; 或 [yourLabel alignBottom];。

 > huntsbot.com高效搞钱,一站式跟进超10+任务平台外包需求

`@DS 我注意到您在 @implementation UILabel 之后的括号之间添加了 VerticalAlign。作为 Objective-C 的新手,我以前没有遇到过这种语法。这个叫什么?`

`太棒了,不知道类别,这让我更加欣赏Objective-c语言。学习更多的语言对于成为一名优秀的程序员非常重要。`

`投了赞成票。但是 iirc 如果您不知道行数,这是行不通的,这是一个缺点`

`我必须显示 3 行文本并将文本对齐到顶部。那么,我是否必须将行数设置为 3。当我将其设置为 3 时,如果文本较少(适合一行),我会看到“...”。如何避免这种“……”`

`我发布了这个类别的编辑,希望它很快就会被批准。方法 sizeWithFont:constrainedToSize:lineBreakMode: 和 sizeWithFont: 在 iOS7 中均已弃用。此外,此类别仅在 numberOfLines 大于 0 时适用于标签。`

# 答4:
> huntsbot.com提供全网独家一站式外包任务、远程工作、创意产品分享与订阅服务!

以防万一它对任何人有任何帮助,我遇到了同样的问题,但只需从使用 UILabel 切换到使用 UITextView 即可解决问题。我很欣赏这并不适合所有人,因为功能有点不同。

 如果您确实切换到使用 UITextView,您可以关闭所有滚动视图属性以及启用用户交互...这将迫使它更像一个标签。

 https://i.stack.imgur.com/HB87m.png

 `如果将许多 UILabel 转换为文本视图,不确定这将如何影响性能。`

`该线程上的所有其他解决方案在 iOS 7 中对我不起作用(无论出于何种原因)。但只需使用 UITextView 即可立即获得所需的结果。`

`这是一种解决方法,它仍然需要一些调整以使其看起来真实,但确实这是我看到的最简单的无代码解决方案,竖起大拇指。`

`我喜欢这个解决方案。当然,可能存在性能问题,例如,对于相对简单的视图上的简单标签,这非常适合我的需要(而且我没有注意到任何性能影响)`

`这种方法的一个小缺点是它会给文本引入额外的内在填充。一个快速的解决方法是引入一个负约束。`

# 答5:
> huntsbot.com -- 程序员副业首选,一站式外包任务、远程工作、创意产品分享订阅平台。

没有混乱,没有大惊小怪

 

```java
@interface MFTopAlignedLabel : UILabel

@end


@implementation MFTopAlignedLabel

- (void)drawTextInRect:(CGRect) rect
{
    NSAttributedString *attributedText = [[NSAttributedString alloc]     initWithString:self.text attributes:@{NSFontAttributeName:self.font}];
    rect.size.height = [attributedText boundingRectWithSize:rect.size
                                            options:NSStringDrawingUsesLineFragmentOrigin
                                            context:nil].size.height;
    if (self.numberOfLines != 0) {
        rect.size.height = MIN(rect.size.height, self.numberOfLines * self.font.lineHeight);
    }
    [super drawTextInRect:rect];
}

@end

没有混乱,没有 Objective-c,没有大惊小怪,只有 Swift 3:

class VerticalTopAlignLabel: UILabel {

    override func drawText(in rect:CGRect) {
        guard let labelText = text else {  return super.drawText(in: rect) }

        let attributedText = NSAttributedString(string: labelText, attributes: [NSFontAttributeName: font])
        var newRect = rect
        newRect.size.height = attributedText.boundingRect(with: rect.size, options: .usesLineFragmentOrigin, context: nil).size.height

        if numberOfLines != 0 {
            newRect.size.height = min(newRect.size.height, CGFloat(numberOfLines) * font.lineHeight)
        }

        super.drawText(in: newRect)
    }

}

斯威夫特 4.2

class VerticalTopAlignLabel: UILabel {

    override func drawText(in rect:CGRect) {
        guard let labelText = text else {  return super.drawText(in: rect) }

        let attributedText = NSAttributedString(string: labelText, attributes: [NSAttributedString.Key.font: font])
        var newRect = rect
        newRect.size.height = attributedText.boundingRect(with: rect.size, options: .usesLineFragmentOrigin, context: nil).size.height

        if numberOfLines != 0 {
            newRect.size.height = min(newRect.size.height, CGFloat(numberOfLines) * font.lineHeight)
        }

        super.drawText(in: newRect)
    }

}

快速版本对我有用,没有任何副作用!做得好!

可能是这里最好的答案,适用于所有场景。如果标签位于 UITableviewCell 中,则 sizeToFit 不起作用。干得好。

亲爱的 Apple,让文本自动转到左上角应该不难。也就是说,@jasongregori 这里的答案很好。尝试了拥抱概念和最佳答案,并且没有为 CollectionViewCell 标签工作。 UILabel 的自定义类是解决方案。

对于那些不了解自定义类概念的人,请使用以下方法修复上述答案: 1. 在您的项目中创建一个新的 Swift 文件。 COMMAND + N. 2. 为自定义 UILabel 类插入下图所示的代码。 3. 不要忘记将 UIKit 导入到这个文件中,否则你会在这段代码上到处看到红色,从 XCode 开始没有将“UILabel”识别为类类型。 4. 另外不要忘记进入标签的身份检查器以切换自定义类并找到“VerticalTopAlignLabel”或您命名的任何名称。

答6:

一个优秀的自由职业者,应该有对需求敏感和精准需求捕获的能力,而huntsbot.com提供了这个机会

使用 Storyboard 的最简单方法:

将 Label 嵌入到 StackView 中,并在 Attribute Inspector 中设置 StackView 的以下两个属性:

1- Axis 到 Horizontal,

2- Alignment 到 Top

https://i.stack.imgur.com/SVs0w.png

为了获得更好的结果,您可以执行此 StackView > View > UILabel,因为当您只是在 StackView 中嵌入 UILabel 时,StackView 会调整大小以适合 UILabel 到最小尺寸

将 UILabel 放入某个 UIView 子类(普通的 UIView 通常就足够了)并让该标签向下增长的好主意。谢谢!

使用 Editor->Embed 菜单命令并选择您的标签,Xcode 会为您清除标签约束,然后您可以为 StackView 设置约束。这种方法最接近我发现它的“SwiftUI”布局方法。

您不需要 UIStackView,只需将 UILabel 嵌入到 UIView 中。设置 UIView 约束以占用 UILabel 应增长到的最大空间。然后将 UILabel 设置为 UIView 的顶部、右侧和左侧,并将距离 >= 0 的约束也设置为底部。

答7:

保持自己快人一步,享受全网独家提供的一站式外包任务、远程工作、创意产品订阅服务–huntsbot.com

就像上面的答案一样,但它不太正确,或者很容易打入代码,所以我对其进行了一些清理。将此扩展名添加到它自己的 .h 和 .m 文件中,或者直接粘贴到您打算使用它的实现上方:

#pragma mark VerticalAlign
@interface UILabel (VerticalAlign)
- (void)alignTop;
- (void)alignBottom;
@end


@implementation UILabel (VerticalAlign)
- (void)alignTop
{
    CGSize fontSize = [self.text sizeWithFont:self.font];

    double finalHeight = fontSize.height * self.numberOfLines;
    double finalWidth = self.frame.size.width;    //expected width of label


    CGSize theStringSize = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(finalWidth, finalHeight) lineBreakMode:self.lineBreakMode];


    int newLinesToPad = (finalHeight  - theStringSize.height) / fontSize.height;

    for(int i=0; i<= newLinesToPad; i++)
    {
        self.text = [self.text stringByAppendingString:@" \n"];
    }
}

- (void)alignBottom
{
    CGSize fontSize = [self.text sizeWithFont:self.font];

    double finalHeight = fontSize.height * self.numberOfLines;
    double finalWidth = self.frame.size.width;    //expected width of label


    CGSize theStringSize = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(finalWidth, finalHeight) lineBreakMode:self.lineBreakMode];


    int newLinesToPad = (finalHeight  - theStringSize.height) / fontSize.height;

    for(int i=0; i< newLinesToPad; i++)
    {
        self.text = [NSString stringWithFormat:@" \n%@",self.text];
    }
}
@end

然后使用,将你的文本放入标签中,然后调用适当的方法来对齐它:

[myLabel alignTop];

或者

[myLabel alignBottom];

sizeWithFont 已弃用

答8:

HuntsBot周刊–不定时分享成功产品案例,学习他们如何成功建立自己的副业–huntsbot.com

一种更快(也更脏)的方法是将 UILabel 的换行模式设置为“Clip”并添加固定数量的换行符。

myLabel.lineBreakMode = UILineBreakModeClip;
myLabel.text = [displayString stringByAppendingString:"\n\n\n\n"];

此解决方案不适用于所有人 - 特别是,如果您仍想在字符串末尾显示“…”,如果它超过了您显示的行数,则需要使用其中之一更长的代码位——但在很多情况下,这会让你得到你需要的东西。

将换行模式设置为“剪辑”似乎会扰乱标签的自动调整大小。请改用 UILineBreakModeWordWrap。

并更好地添加空格“ \n \n ”

答9:

huntsbot.com全球7大洲远程工作机会,探索不一样的工作方式

您可以使用具有垂直对齐选项的 UITextField 而不是 UILabel:

textField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
textField.userInteractionEnabled = NO; // Don't allow interaction

警告: UITextField 只允许单行文本。

完成@DavidJames 评论: UITextView 会更合适

答10:

HuntsBot周刊–不定时分享成功产品案例,学习他们如何成功建立自己的副业–huntsbot.com

我已经为此苦苦挣扎了很长时间,我想分享我的解决方案。

这将为您提供一个 UILabel,它会将文本自动缩小到 0.5 比例并将文本垂直居中。这些选项在 Storyboard/IB 中也可用。

[labelObject setMinimumScaleFactor:0.5];
[labelObject setBaselineAdjustment:UIBaselineAdjustmentAlignCenters];

在提供的所有答案中,它表现得非常完美。谢谢@David Greco。除了这些属性,如果我们将 adjustsFontSizeToFitWidth 设置为 YES,那么文本将适合框架而不修改标签的框架。

答11:

huntsbot.com汇聚了国内外优秀的初创产品创意,可按收入、分类等筛选,希望这些产品与实践经验能给您带来灵感。

创建一个新类

标签顶部对齐

.h 文件

#import 


@interface KwLabelTopAlign : UILabel {

}

@end

.m 文件

#import "KwLabelTopAlign.h"


@implementation KwLabelTopAlign

- (void)drawTextInRect:(CGRect)rect {
    int lineHeight = [@"IglL" sizeWithFont:self.font constrainedToSize:CGSizeMake(rect.size.width, 9999.0f)].height;
    if(rect.size.height >= lineHeight) {
        int textHeight = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(rect.size.width, rect.size.height)].height;
        int yMax = textHeight;
        if (self.numberOfLines > 0) {
            yMax = MIN(lineHeight*self.numberOfLines, yMax);    
        }

        [super drawTextInRect:CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, yMax)];
    }
}

@end

编辑

这是一个更简单的实现,它做同样的事情:

#import "KwLabelTopAlign.h"

@implementation KwLabelTopAlign

- (void)drawTextInRect:(CGRect)rect
{
    CGFloat height = [self.text sizeWithFont:self.font
                            constrainedToSize:rect.size
                                lineBreakMode:self.lineBreakMode].height;
    if (self.numberOfLines != 0) {
        height = MIN(height, self.font.lineHeight * self.numberOfLines);
    }
    rect.size.height = MIN(rect.size.height, height);
    [super drawTextInRect:rect];
}

@end

+1 为真正的答案。与 sizeToFit 解决方案不同,这实际上使 UILabel 将 any 文本放在顶部,即使您将较短的文本动态替换为较长的文本,反之亦然。

huntsbot.com聚合了超过10+全球外包任务平台的外包需求,寻找外包任务与机会变的简单与高效。