协慌网

登录 贡献 社区

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

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

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

表示具有垂直居中文本的UILabel的图像

答案

无法在UILabel上设置垂直对齐,但您可以通过更改标签的框架来获得相同的效果。我把标签变成橙色,这样你就可以清楚地看到发生了什么。

这是快速简便的方法:

[myLabel sizeToFit];

sizeToFit来挤压标签


如果您的文本较长的标签将生成多行,请将numberOfLines设置为0 (此处为零表示无限数量的行)。

myLabel.numberOfLines = 0;
    [myLabel sizeToFit];

使用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在评论中使用自动布局修复了 NIB 和故事板:

如果您的标签被包括在笔尖或故事板作为一个子视图view使用自动布局,然后把你的一个视图控制器的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;
  1. 设置新文本:

    myLabel.text = @"Some Text"
  2. maximum numbermaximum number设置为 0(自动):

    myLabel.numberOfLines = 0
  3. 将标签的框架设置为最大尺寸:

    myLabel.frame = CGRectMake(20,20,200,800)
  4. 调用sizeToFit来减小帧大小,使内容适合:

    [myLabel sizeToFit]

现在,标签框架的高度和宽度足以适合您的文字。左上角应保持不变。我只用左上对齐的文本测试了这个。对于其他对齐,您可能必须在之后修改框架。

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

参考扩展解决方案:

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 alignTop];[yourLabel alignBottom];在每个 yourLabel 文本分配之后。