在 UILabel 中将文本垂直对齐到顶部

Posted

技术标签:

【中文标题】在 UILabel 中将文本垂直对齐到顶部【英文标题】:Vertically align text to top within a UILabel 【发布时间】:2009-06-28 08:54:03 【问题描述】:

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

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

【问题讨论】:

见***.com/a/41367948/1108052 【参考方案1】:

无法在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];

标签的大小仍然是固定的左上角。您可以将原始标签的宽度保存在变量中并在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;


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

其他一些注意事项:

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


Mark Amery 修复了在 cmets 中使用自动布局的 NIB 和 Storyboard:

如果您的标签作为使用自动布局的 ViewController 的 view 的子视图包含在 nib 或情节提要中,那么将您的 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;

【讨论】:

你需要删除自动布局 这里有一个简单的解决方法:***.com/a/26632490/636559 这个答案不必要地复杂,它使用的是“周围的词”。请参阅下面关于简单更改垂直内容拥抱优先级的建议。不需要任何代码... [myLabel sizeToFit] 在 UITableViewCells 中不好用,因为这里的标签被重复使用,新文本可能不适合。 您仍然可以使用 AutoLayout 和约束,但要确保 [height] 不会被固定。例如:设置 Left、Top 和 Right 等于 8px,但 Bottom 可以设置“大于或等于”8px。它会对 ios 说,让我的 sizeToFit 为我的标签决定更好的高度。【参考方案2】:

    设置新文本:

    myLabel.text = @"Some Text"
    

    将行的maximum number 设置为0(自动):

    myLabel.numberOfLines = 0
    

    将标签的边框设置为最大尺寸:

    myLabel.frame = CGRectMake(20,20,200,800)
    

    调用sizeToFit 以减小帧大小,使内容刚好适合:

    [myLabel sizeToFit]
    

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

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

【讨论】:

这对我来说很好。我在 IB 中设置了我的 UILabel 的尺寸并将 numberOfLines 更改为 0,然后在设置了名为 [myLabel sizeToFit] 的文本之后。 在 Attr.督察 行数超过 1 行无效 当你想要一个两行的标签时它不起作用,但是文本需要更多行。【参考方案3】:

参考扩展解决方案:

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

应该替换为

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

每个添加的换行符都需要额外的空格,因为 iPhone UILabels' 尾随回车似乎被忽略了:(

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

以下扩展适用于我:

// -- 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<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

然后在每个 yourLabel 文本分配后调用 [yourLabel alignTop];[yourLabel alignBottom];

【讨论】:

@D.S.我注意到您在@implementation UILabel 之后的括号之间添加了VerticalAlign。作为 Objective-C 的新手,我以前没有遇到过这种语法。这叫什么? 太棒了,不知道分类,这让我更加欣赏Objective-c语言。学习更多的语言对于成为一名优秀的程序员非常重要。 投了赞成票。但是如果你不知道行数是不利的,iirc 这将不起作用 我要显示 3 行文本并将文本与顶部对齐。那么,我是否必须将行数设置为 3。当我将其设置为 3 时,如果文本较少(适合一行),我会看到“...”。如何避免这种“...” 我发布了这个类别的编辑,希望它很快就会被批准。 sizeWithFont:constrainedToSize:lineBreakMode: 和 sizeWithFont: 方法在 iOS7 中都被贬值了。此外,此类别仅适用于 numberOfLines 大于 0 的标签。【参考方案4】:

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

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

【讨论】:

不确定如果将许多 UILabel 转换为文本视图,这将如何影响性能。 此线程上的所有其他解决方案在 iOS 7 中对我不起作用(无论出于何种原因)。但只需使用 UITextView 就可以立即获得所需的结果。 这是一种解决方法,它仍然需要一些调整才能使其看起来真实,但确实这是我见过的最简单的无代码解决方案,竖起大拇指。 我喜欢这个解决方案。当然,可能存在性能问题等,对于相对简单的视图上的简单标签,这非常适合我的需要(而且我没有注意到任何性能影响) 这种方法的一个小缺点是它会给文本引入额外的内在填充。一个快速的解决方法是引入一个负约束。【参考方案5】:

不要乱来,不要大惊小怪

@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】:

使用 Storyboard 的最简单方法:

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

1- AxisHorizontal

2- AlignmentTop

【讨论】:

为了获得更好的结果,你可以这样做 StackView > View > UILabel,因为当你只是在 StackView 中嵌入 UILabel 时,StackView 会调整大小以适应 UILabel 到最小尺寸 UILabel 放入一些UIView 子类(普通UIView 通常就足够了)并让标签向下增长的好主意。谢谢! 使用 Editor->Embed 菜单命令并选择标签,Xcode 会为您清除标签约束,然后您可以为 StackView 设置约束。这种方法最接近我发现它的“SwiftUI”布局方法。 您不需要UIStackView,只需将UILabel 嵌入UIView 中即可。设置UIView 约束以占用UILabel 应该增长到的最大空间。然后将UILabel 设置为UIView 的顶部、右侧和左侧,并将约束也设置为底部距离&gt;= 0【参考方案7】:

就像上面的答案,但它不太正确,或者很容易插入代码,所以我把它清理了一下。将此扩展添加到它自己的 .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】:

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

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

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

【讨论】:

将换行模式设置为“剪辑”似乎会扰乱标签的自动调整大小。请改用UILineBreakModeWordWrap 和更好的添加空格“\n \n”【参考方案9】:

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

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

【讨论】:

警告:UITextField 只允许单行文本。 完成@DavidJames 评论:UITextView 会更合适【参考方案10】:

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

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

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

【讨论】:

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

创建一个新类

标签顶部对齐

.h 文件

#import <UIKit/UIKit.h>


@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 解决方案不同,这实际上使 UILabelany 文本放在顶部,即使您动态地将较短的文本替换为较长的文本,反之亦然。【参考方案12】:

在界面生成器中

UILabel 设置为最大可能文本的大小 在属性检查器中将Lines 设置为“0”

在你的代码中

设置标签的文字 在您的标签上致电sizeToFit

代码片段:

self.myLabel.text = @"Short Title";
[self.myLabel sizeToFit];

【讨论】:

工作得很好,除了在我的情况下,我需要将行设置为 2 - 在 UITableViewCell 中有一个 UILabel 并设置为 0 使其重叠,但设置为 2 有效(单元格有足够的空间容纳 2行)【参考方案13】:

对于自适应 UI(iOS8 或更高版本),UILabel 的垂直对齐将通过更改属性从 StoryBoard 设置 noOfLines=0` 和

约束

    调整 UILabel LefMargin、RightMargin 和上边距约束。

    更改Content Compression Resistance Priority For Vertical=1000` 使 Vertical>Horizo​​ntal 。

已编辑:

noOfLines=0

并且以下约束足以达到预期的效果。

【讨论】:

这太棒了。你能解释一下为什么垂直>水平做这项工作吗?谢谢。【参考方案14】:

创建 UILabel 的子类。像魅力一样工作:

// TopLeftLabel.h

#import <Foundation/Foundation.h>

@interface TopLeftLabel : UILabel 



@end

// TopLeftLabel.m

#import "TopLeftLabel.h"

@implementation TopLeftLabel

- (id)initWithFrame:(CGRect)frame 

    return [super initWithFrame:frame];


- (CGRect)textRectForBounds:(CGRect)bounds limitedToNumberOfLines:(NSInteger)numberOfLines 

    CGRect textRect = [super textRectForBounds:bounds limitedToNumberOfLines:numberOfLines];    
    textRect.origin.y = bounds.origin.y;
    return textRect;


-(void)drawTextInRect:(CGRect)requestedRect 

    CGRect actualRect = [self textRectForBounds:requestedRect limitedToNumberOfLines:self.numberOfLines];
    [super drawTextInRect:actualRect];


@end

正如here所讨论的那样。

【讨论】:

【参考方案15】:

我在我的应用程序中所做的是将 UILabel 的 line 属性设置为 0,并创建 UILabel 的底部约束并确保将其设置为 >= 0,如下图所示。

【讨论】:

我不知道为什么这不是公认的答案。比那个简单得多。不错的答案! 是的!这就是我一直在寻找的。这应该是公认的答案。 迄今为止最好的答案。谢谢! +1【参考方案16】:

我写了一个 util 函数来达到这个目的。你可以看看:

// 调整多行标签的高度,使其与顶部垂直对齐 + (void) alignLabelWithTop:(UILabel *)label CGSize maxSize = CGSizeMake(label.frame.size.width, 999); label.adjustsFontSizeToFitWidth = NO; // 获取实际高度 CGSize actualSize = [label.text sizeWithFont:label.font constrainedToSize:maxSize lineBreakMode:label.lineBreakMode]; CGRect rect = label.frame; rect.size.height = 实际尺寸.height; label.frame = 矩形;

.如何使用? (如果 lblHello 是 Interface builder 创建的,所以我跳过了一些 UILabel 属性细节)

lblHello.text = @"Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!"; lblHello.numberOfLines = 5; [使用 alignLabelWithTop:lblHello];

我也在我的博客上写了一篇文章: http://fstoke.me/blog/?p=2819

【讨论】:

【参考方案17】:

我花了一点时间阅读代码,以及介绍页面中的代码,发现他们都尝试修改标签的框架大小,以便不会出现默认的中心垂直对齐。

但是,在某些情况下,我们确实希望标签占据所有这些空间,即使标签确实有很多文本(例如,具有相同高度的多行)。

在这里,我使用了另一种方法来解决它,只需将换行符填充到标签末尾(请注意,我实际上继承了UILabel,但这不是必需的):

CGSize fontSize = [self.text sizeWithFont:self.font];

finalHeight = fontSize.height * self.numberOfLines;
finalWidth = 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 "];

【讨论】:

【参考方案18】:

使用textRect(forBounds:limitedToNumberOfLines:)

class TopAlignedLabel: UILabel 
  override func drawText(in rect: CGRect) 
    let textRect = super.textRect(forBounds: bounds, limitedToNumberOfLines: numberOfLines)
    super.drawText(in: textRect)
  

【讨论】:

你先生是神! 这个答案应该得到方式更多的支持,因为它是迄今为止最好和最干净的解决方案! 很好。它引导我走向正确的方向,使我的标签垂直居中。 非常优雅的解决方案【参考方案19】:

我在这里接受了建议并创建了一个视图,该视图可以包装 UILabel 并将其调整大小并设置行数以使其顶部对齐。简单地把一个 UILabel 作为一个子视图:

@interface TopAlignedLabelContainer : UIView



@end

@implementation TopAlignedLabelContainer

- (void)layoutSubviews

    CGRect bounds = self.bounds;

    for (UILabel *label in [self subviews])
    
        if ([label isKindOfClass:[UILabel class]])
        
            CGSize fontSize = [label.text sizeWithFont:label.font];

            CGSize textSize = [label.text sizeWithFont:label.font
                                     constrainedToSize:bounds.size
                                         lineBreakMode:label.lineBreakMode];

            label.numberOfLines = textSize.height / fontSize.height;

            label.frame = CGRectMake(0, 0, textSize.width,
                 fontSize.height * label.numberOfLines);
        
    


@end

【讨论】:

【参考方案20】:

你可以使用TTTAttributedLabel,它支持垂直对齐。

@property (nonatomic) TTTAttributedLabel* label;
<...>

//view's or viewController's init method
_label.verticalAlignment = TTTAttributedLabelVerticalAlignmentTop;

【讨论】:

【参考方案21】:

我发现这个问题的答案现在有点过时了,所以为那里的自动布局爱好者添加这个。

自动布局使这个问题变得非常简单。假设我们将标签添加到UIView *view,以下代码将完成此操作:

UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];
[label setText:@"Some text here"];
[label setTranslatesAutoresizingMaskIntoConstraints:NO];
[view addSubview:label];

[view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[label]|" options:0 metrics:nil views:@@"label": label]];
[view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[label]" options:0 metrics:nil views:@@"label": label]];

标签的高度将被自动计算(使用它的intrinsicContentSize)并且标签将被水平边对边放置在view的顶部。

【讨论】:

【参考方案22】:

上面的方法我用过很多,只是想补充一下我用过的又快又脏的方法:

myLabel.text = [NSString stringWithFormat:@"%@\n\n\n\n\n\n\n\n\n",@"My label text string"];

确保字符串中换行符的数量会导致任何文本填满可用的垂直空间,并设置 UILabel 以截断任何溢出的文本。

因为有时候足够好就是足够好

【讨论】:

但是考虑到 iOS 设备屏幕尺寸高度的变化,需要有一个可变数量的 '\n' 来解释 uilabel 改变高度(这是可能的)。因此,从长远来看,这种方法并不是特别有用。 注意:“快速而肮脏的”不是“永远的完美解决方案”。只是说。 @CodeRoadie 又快又脏对我有用,我在真正的答案中遇到了一些布局问题。我可以以“正确的方式”做到这一点,但感谢您为我节省了一些时间! @dGambit 请注意:“快且 我最近在使用UITextView 动态加载视图时学到的一点是,它可以调用dlopen 来支持文本输入。这可能会导致 UI 线程严重滞后,因此这种方法的性能要高得多!【参考方案23】:

我想要一个标签,它能够有多行、最小字体大小,并且在它的父视图中水平和垂直居中。我以编程方式将标签添加到视图中:

- (void) customInit 
    // Setup label
    self.label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
    self.label.numberOfLines = 0;
    self.label.lineBreakMode = UILineBreakModeWordWrap;
    self.label.textAlignment = UITextAlignmentCenter;

    // Add the label as a subview
    self.autoresizesSubviews = YES;
    [self addSubview:self.label];

然后当我想更改标签的文本时...

- (void) updateDisplay:(NSString *)text 
    if (![text isEqualToString:self.label.text]) 
        // Calculate the font size to use (save to label's font)
        CGSize textConstrainedSize = CGSizeMake(self.frame.size.width, INT_MAX);
        self.label.font = [UIFont systemFontOfSize:TICKER_FONT_SIZE];
        CGSize textSize = [text sizeWithFont:self.label.font constrainedToSize:textConstrainedSize];
        while (textSize.height > self.frame.size.height && self.label.font.pointSize > TICKER_MINIMUM_FONT_SIZE) 
            self.label.font = [UIFont systemFontOfSize:self.label.font.pointSize-1];
            textSize = [ticker.blurb sizeWithFont:self.label.font constrainedToSize:textConstrainedSize];
        
        // In cases where the frame is still too large (when we're exceeding minimum font size),
        // use the views size
        if (textSize.height > self.frame.size.height) 
            textSize = [text sizeWithFont:self.label.font constrainedToSize:self.frame.size];
        

        // Draw 
        self.label.frame = CGRectMake(0, self.frame.size.height/2 - textSize.height/2, self.frame.size.width, textSize.height);
        self.label.text = text;
    
    [self setNeedsDisplay];

希望对某人有所帮助!

【讨论】:

【参考方案24】:

FXLabel (on github) 通过将label.contentMode 设置为UIViewContentModeTop 开箱即用地执行此操作。这个组件不是我做的,但它是我经常使用的组件,有很多功能,而且看起来很好用。

【讨论】:

【参考方案25】:

对于因标签内的文本未垂直居中而阅读本文的任何人,请记住,某些字体类型的设计并不相同。例如,如果您创建一个 zapfino 大小为 16 的标签,您会看到文本没有完全垂直居中。

但是,使用 helvetica 会使您的文本垂直居中。

【讨论】:

许多自定义字体不是垂直居中对齐的。 UILabel 或 UITextView 始终垂直居中对齐。在 iOS 编程中无需考虑垂直对齐。【参考方案26】:

子类 UILabel 并约束绘图矩形,如下所示:

- (void)drawTextInRect:(CGRect)rect

    CGSize sizeThatFits = [self sizeThatFits:rect.size];
    rect.size.height = MIN(rect.size.height, sizeThatFits.height);

    [super drawTextInRect:rect];

我尝试了涉及换行符填充的解决方案,但在某些情况下遇到了不正确的行为。根据我的经验,像上面那样约束绘图矩形比使用numberOfLines 更容易。

附:您可以想象以这种方式轻松支持 UIViewContentMode:

- (void)drawTextInRect:(CGRect)rect

    CGSize sizeThatFits = [self sizeThatFits:rect.size];

    if (self.contentMode == UIViewContentModeTop) 
        rect.size.height = MIN(rect.size.height, sizeThatFits.height);
    
    else if (self.contentMode == UIViewContentModeBottom) 
        rect.origin.y = MAX(0, rect.size.height - sizeThatFits.height);
        rect.size.height = MIN(rect.size.height, sizeThatFits.height);
    

    [super drawTextInRect:rect];

【讨论】:

【参考方案27】:

如果您使用自动布局,请在代码或 IB 中将垂直 contentHuggingPriority 设置为 1000。在 IB 中,您可能必须通过将其优先级设置为 1 然后删除它来移除高度限制。

【讨论】:

【参考方案28】:

只要你不做任何复杂的任务,你可以用UITextView代替UILabels

禁用滚动。

如果您希望文本完全显示,只需用户 sizeToFitsizeThatFits: 方法

【讨论】:

【参考方案29】:

很快,

let myLabel : UILabel!

使标签的文本适合屏幕并且位于顶部

myLabel.sizeToFit()

使您的标签字体适合屏幕宽度或特定宽度大小。

myLabel.adjustsFontSizeToFitWidth = YES

还有一些用于标签的 textAlignment :

myLabel.textAlignment = .center

myLabel.textAlignment = .left

myLabel.textAlignment = .right

myLabel.textAlignment = .Natural

myLabel.textAlignment = .Justified

【讨论】:

只是对 [myLabel sizeToFit] 旧语法的语法更改。谢谢!【参考方案30】:

这是一个旧的解决方案,在 iOS >= 6 上使用自动布局

我的解决方案:

    自己拆分行(忽略标签换行设置) 自己画线(忽略标签对齐)

@interface UITopAlignedLabel : UILabel

@end

@implementation UITopAlignedLabel

#pragma mark Instance methods

- (NSArray*)splitTextToLines:(NSUInteger)maxLines 
    float width = self.frame.size.width;

    NSArray* words = [self.text componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    NSMutableArray* lines = [NSMutableArray array];

    NSMutableString* buffer = [NSMutableString string];    
    NSMutableString* currentLine = [NSMutableString string];

    for (NSString* word in words) 
        if ([buffer length] > 0) 
            [buffer appendString:@" "];
        

        [buffer appendString:word];

        if (maxLines > 0 && [lines count] == maxLines - 1) 
            [currentLine setString:buffer];
            continue;
        

        float bufferWidth = [buffer sizeWithFont:self.font].width;

        if (bufferWidth < width) 
            [currentLine setString:buffer];
        
        else 
            [lines addObject:[NSString stringWithString:currentLine]];

            [buffer setString:word];
            [currentLine setString:buffer];
        
    

    if ([currentLine length] > 0) 
        [lines addObject:[NSString stringWithString:currentLine]];
    

    return lines;


- (void)drawRect:(CGRect)rect 
    if ([self.text length] == 0) 
        return;
    

    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextSetFillColorWithColor(context, self.textColor.CGColor);
    CGContextSetShadowWithColor(context, self.shadowOffset, 0.0f, self.shadowColor.CGColor);

    NSArray* lines = [self splitTextToLines:self.numberOfLines];
    NSUInteger numLines = [lines count];

    CGSize size = self.frame.size;
    CGPoint origin = CGPointMake(0.0f, 0.0f);

    for (NSUInteger i = 0; i < numLines; i++) 
        NSString* line = [lines objectAtIndex:i];

        if (i == numLines - 1) 
            [line drawAtPoint:origin forWidth:size.width withFont:self.font lineBreakMode:UILineBreakModeTailTruncation];            
        
        else 
            [line drawAtPoint:origin forWidth:size.width withFont:self.font lineBreakMode:UILineBreakModeClip];
        

        origin.y += self.font.lineHeight;

        if (origin.y >= size.height) 
            return;
        
    


@end

【讨论】:

以上是关于在 UILabel 中将文本垂直对齐到顶部的主要内容,如果未能解决你的问题,请参考以下文章

在 UILabel 中将文本垂直对齐到顶部

将 select 和 input 元素中的文本垂直对齐到顶部

我想在选择框中垂直对齐文本

我想在选择框中垂直对齐文本

如何将 TextView 容器内的文本对齐到顶部? [复制]

如何将 UIButton 文本与 UILabel 文本垂直对齐?