ios 垂直对齐 UILabel

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

Vertically align UILabel

iosxcodeuilabel

提问by Ashish Agarwal

I am trying to vertically align the text in the UILabel view of my app. The problem is that I want the text to be vertically aligned to the top and the size of the label to be 280 x 150. I am only able to achieve one of these 2 things. If I remove the line

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

[myLabel sizeToFit];

then the alignment of the text is alright but the size is messed up. But if I add the above line, then the alignment is messed up but the size is alright. How do I fix this problem.

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

I've added the code below -

我在下面添加了代码 -

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

回答by Vaibhav Saran

dont use UILabelfor this. Use UIButtonwith UserInteractionEnabled = NO;and that has options to vertical or horizontal align text inside it.

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

Here you go:

干得好:

Swift:

迅速:

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


Obj-C

对象-C

[btnDetail.titleLabel setNumberOfLines:5];
[btnDetail.titleLabel setLineBreakMode:NSLineBreakByCharWrapping];
[btnDetail setContentVerticalAlignment:UIControlContentVerticalAlignmentTop];
[btnDetail setContentHorizontalAlignment:UIControlContentHorizontalAlignmentLeft];
[btnDetail setUserInteractionEnabled:NO];
btnDetail.autoresizesSubviews = YES;
btnDetail.autoresizingMask = UIViewAutoresizingFlexibleWidth;

回答by Nick Lockwood

I'm the author of FXLabel, and whilst I don't know Manish, I believe he was trying to help (if he was advertising for me, I certainly didn't ask him to, and I'm not paying him - sorry Manish!).

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

One of FXLabel's features is that it respects the UIContentMode property of the label, as set in Interface builder. This means you can set label.contentMode = UIViewContentModeTop; to align the text to the top of the label view (which doesn't work for a regular UILabel). The relevant example is here:

FXLabel 的功能之一是它遵守在界面构建器中设置的标签的 UIContentMode 属性。这意味着您可以设置 label.contentMode = UIViewContentModeTop; 将文本与标签视图的顶部对齐(这不适用于常规 UILabel)。相关示例在这里:

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

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

FXLabel is a drop-in subclass of UILabel, so I think it's a pretty good solution for the question being posed. However if the poster would rather solve the problem without using a 3rd party library (which is understandable) then here is the code to do it:

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

Note:(This is untested, so apologies if there are any typos)

注意:(这是未经测试的,所以如果有任何错别字,请见谅)

回答by jrc

You'll need to subclass UILabel. Try this:

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

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

    [super drawTextInRect:rect];
}

As you've discovered, UILabel vertically centers text within its bounds. Here we ask -sizeThatFitsfor the text block size and uses it to constrain the drawing rectangle passed to UILabel, so that text is drawn from the top of the label bounds.

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

You could even support the ignored (sigh) contentModeproperty like this:

您甚至可以支持这样的忽略(叹气)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];
}

There's a bunch of other solutions and discussion here: Vertically align text to top within a UILabel

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

回答by Roshambo

In Swift, JRC's solution of subclassing UILabel, overriding drawTextInRectand conforming to UIViewContentModewould look like this:

在 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)
    }

}

Implementing is simply a matter of:

实施只是一个问题:

yourLabel.contentMode = UIViewContentMode.top

For me, it worked like a charm.

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

回答by Joffrey Outtier

You can make it with a constraint on the interface builder.

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

  1. Put the number of lines that you want
  2. Create a constraint with an height enough bigger for 3 lines and in relation section put "Less Than or Equal".
  1. 输入你想要的行数
  2. 创建一个高度足以容纳 3 行的约束,并在关系部分放置“小于或等于”。

Hope this help you !

希望这对你有帮助!

回答by Cocoadelica

There's a way without subclassing, using a button or rolling your own.

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

set the number of lines to 0, then call sizeToFit.

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

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

More details here as i think someone else linked to: Vertically align text to top within a UILabel

更多细节,因为我认为其他人链接到:Vertically align text to top inside a UILabel

回答by Dan G

In addition to the above recommending setting the number of lines to 0 and the line break to Word Wrap be sure to not specify a height constraint. New lines are automatically added as needed by the displayed text and the text is always vertically aligned to the top of the label.

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

回答by ingconti

nice hack... my two cents for swift 4.2/5:

不错的 hack ......我的 swift 4.2/5 两美分:

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

and add \n.. as suggested..

并按照建议添加 \n..

回答by Thomás Calmon

I did it what you want by implementing a category:

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

.h

。H

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

.m

.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

Remember that you need to set "NumberOfLines" to 0. This example works with multilines options!

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

After you implement above category, you can simply do:

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

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

Cheers!

干杯!

回答by Fahim Parkar

You can do it as follows.......

您可以按照以下方式进行......

  1. Set your label's numberOfLinesproperty 0 from IB

  2. Set your label's lineBreakModeas UILineBreakModeWordWrap(very very important)

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

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

now whatever you set on the label just append few @"\n" to it..... ex.-

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

[yourTextLabel setText:@"myLabel\n\n\n\n\n"];