11

我正在尝试在我的应用程序的 UILabel 视图中垂直对齐文本。问题是我希望文本与顶部垂直对齐,标签的大小为 280 x 150。我只能实现这两件事之一。如果我删除线

[myLabel sizeToFit];

然后文本的对齐是好的,但大小搞砸了。但是如果我添加上面的行,那么对齐就会搞砸但大小还可以。我该如何解决这个问题。

我在下面添加了代码 -

CGRect labelFrame = CGRectMake(22, 50, 280, 150);
UILabel *myLabel = [[UILabel alloc] initWithFrame:labelFrame];
[myLabel setText:finalRecipe];
[myLabel setBackgroundColor: [UIColor lightGrayColor]];
[myLabel setNumberOfLines:0];
[myLabel sizeToFit];
[self.view addSubview:myLabel];
4

10 回答 10

19

不要UILabel用于此。使用UIButtonwithUserInteractionEnabled = NO;并且可以选择垂直或水平对齐其中的文本。

干得好:

迅速:

btnDetail.titleLabel?.numberOfLines = 5
btnDetail.titleLabel?.lineBreakMode = .byCharWrapping
btnDetail.contentVerticalAlignment = .top
btnDetail.contentHorizontalAlignment = .left
btnDetail.isUserInteractionEnabled = false
btnDetail.autoresizesSubviews = true
btnDetail.autoresizingMask = .flexibleWidth

对象-C

[btnDetail.titleLabel setNumberOfLines:5];
[btnDetail.titleLabel setLineBreakMode:NSLineBreakByCharWrapping];
[btnDetail setContentVerticalAlignment:UIControlContentVerticalAlignmentTop];
[btnDetail setContentHorizontalAlignment:UIControlContentHorizontalAlignmentLeft];
[btnDetail setUserInteractionEnabled:NO];
btnDetail.autoresizesSubviews = YES;
btnDetail.autoresizingMask = UIViewAutoresizingFlexibleWidth;
于 2013-03-28T08:23:05.240 回答
13

我是 FXLabel 的作者,虽然我不认识 Manish,但我相信他是想帮忙(如果他为我做广告,我当然没有要求他这样做,我也没有付钱给他 - 抱歉曼尼什!)。

FXLabel 的功能之一是它尊重标签的 UIContentMode 属性,如 Interface builder 中设置的那样。这意味着您可以设置 label.contentMode = UIViewContentModeTop; 将文本与标签视图的顶部对齐(这不适用于常规 UILabel)。相关示例在这里:

https://github.com/nicklockwood/FXLabel/tree/master/Examples/Text%20Alignment

FXLabel 是 UILabel 的一个插入子类,所以我认为它对于提出的问题来说是一个很好的解决方案。但是,如果发布者宁愿在不使用 3rd 方库的情况下解决问题(这是可以理解的),那么这里是执行此操作的代码:

CGRect labelFrame = CGRectMake(22, 50, 280, 150);
UILabel *myLabel = [[UILabel alloc] initWithFrame:labelFrame];
[myLabel setText:finalRecipe];
[myLabel setBackgroundColor: [UIColor lightGrayColor]];
[myLabel setNumberOfLines:0];

CGFloat fontSize = 0.0f;
labelFrame.size = [myLabel.text sizeWithFont:myLabel.font
                                minFontSize:myLabel.minimumFontSize
                             actualFontSize:&fontSize
                                   forWidth:labelFrame.width
                            lineBreakMode:myLabel.lineBreakMode];

myLabel.frame = labelFrame;
[self.view addSubview:myLabel];

注:(本文未经测试,如有错误请见谅)

于 2012-07-01T00:17:58.993 回答
12

您需要继承 UILabel。尝试这个:

- (void)drawTextInRect:(CGRect)rect
{
    CGSize sizeThatFits = [self sizeThatFits:rect.size];
    rect.size.height = MIN(rect.size.height, sizeThatFits.height);

    [super drawTextInRect:rect];
}

正如您所发现的,UILabel 在其边界内垂直居中文本。这里我们要求-sizeThatFits文本块的大小并使用它来约束传递给 UILabel 的绘图矩形,以便从标签边界的顶部绘制文本。

你甚至可以contentMode像这样支持被忽略的(叹气)属性:

- (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];
}

这里还有很多其他的解决方案和讨论: Vertically align text to top within a UILabel

于 2012-07-03T15:12:45.243 回答
11

在 Swift 中,JRC 的子类化UILabel、覆盖drawTextInRect和符合的解决方案UIViewContentMode如下所示:

class AlignableUILabel: UILabel {

    override func drawText(in rect: CGRect) {

        var newRect = CGRect(x: rect.origin.x,y: rect.origin.y,width: rect.width, height: rect.height)
        let fittingSize = sizeThatFits(rect.size)

        if contentMode == UIViewContentMode.top {
            newRect.size.height = min(newRect.size.height, fittingSize.height)
        } else if contentMode == UIViewContentMode.bottom {
            newRect.origin.y = max(0, newRect.size.height - fittingSize.height)
        }

        super.drawText(in: newRect)
    }

}

实施只是一个简单的问题:

yourLabel.contentMode = UIViewContentMode.top

对我来说,它就像一种魅力。

于 2015-03-21T16:12:05.483 回答
1

有一种方法无需子类化,使用按钮或滚动您自己的。

将行数设置为 0,然后调用 sizeToFit。

[label setNumberOfLines:0];
[label sizeToFit];

我认为其他人链接到的更多详细信息:在 UILabel 中将文本垂直对齐到顶部

于 2013-08-22T14:33:47.710 回答
1

除了上述建议将行数设置为 0 并将换行符设置为 Word Wrap 之外,请务必不要指定高度限制。显示的文本会根据需要自动添加新行,并且文本始终垂直对齐到标签的顶部。

于 2019-12-18T21:15:48.450 回答
1

您可以通过对界面构建器的约束来实现它。

  1. 把你想要的行数
  2. 创建一个高度足以容纳 3 行的约束,并在相关部分放置“小于或等于”。

希望这对你有帮助!

于 2016-10-26T13:46:10.093 回答
0

我通过实现一个类别做到了你想要的:

。H

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

.m

@implementation UILabel (VerticalAlign)

#pragma mark
#pragma mark - Align Methods

- (void)alignTop
{
    [self setFrame:[self newLabelFrame:UIControlContentVerticalAlignmentTop]];
}

- (void)alignBottom
{
    [self setFrame:[self newLabelFrame:UIControlContentVerticalAlignmentBottom]];
}

#pragma mark
#pragma mark - Helper Methods

- (CGRect)newLabelFrame:(UIControlContentVerticalAlignment)alignment
{
    CGRect labelRect = self.frame;

    NSStringDrawingOptions options = NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesFontLeading;

    CGRect textRect = [self.text boundingRectWithSize:CGSizeMake(227.f, CGFLOAT_MAX)
                                              options:options
                                           attributes:@{NSFontAttributeName:self.font}
                                              context:nil];

    CGFloat textOffset = labelRect.size.height - textRect.size.height;

    UIEdgeInsets contentInsets;
    if (alignment == UIControlContentVerticalAlignmentTop)
    {
        if (textOffset < (labelRect.size.height/2.f))
        {
            contentInsets = UIEdgeInsetsMake(-textOffset, 0.f, 0.f, 0.f);
        }
        else
        {
            contentInsets = UIEdgeInsetsMake(0.f, 0.f, textOffset, 0.f);
        }
    }
    else
    {
        if (textOffset < (labelRect.size.height/2.f))
        {
            contentInsets = UIEdgeInsetsMake(0.f, 0.f, -textOffset, 0.f);
        }
        else
        {
            contentInsets = UIEdgeInsetsMake(textOffset, 0.f, 0.f, 0.f);
        }
    }

    return UIEdgeInsetsInsetRect(labelRect, contentInsets);
}

@end

请记住,您需要将“NumberOfLines”设置为 0。此示例适用于多行选项!

实现上述类别后,您可以简单地执行以下操作:

[myLabel setText:finalRecipe];
[myLabel alignTop];

干杯!

于 2014-08-23T14:49:21.890 回答
0

不错的技巧...我为 swift 4.2/5 提供的两分钱:

self.optTextMessage.numberOfLines =  0
self.optTitle.lineBreakMode  = .byWordWrapping

并按照建议添加 \n..

于 2019-03-02T18:05:49.957 回答
-2

你可以这样做......

  1. numberOfLines从 IB设置标签的属性 0

  2. 将您的标签设置lineBreakModeUILineBreakModeWordWrap非常非常重要

现在无论您在标签上设置什么,只需在其上附加几个 @"\n" ......例如 -

[yourTextLabel setText:@"myLabel\n\n\n\n\n"];
于 2013-10-17T20:57:02.050 回答