ios - uilabel行间距 - uilabel顶部对齐




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

  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]

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

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

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

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


FXLabel(在github上)通过将label.contentMode设置为UIViewContentModeTop 。 这个组件不是由我制作的,但它是我经常使用的组件,具有大量功能,并且似乎运行良好。


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

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


创建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所讨论的。


参考扩展解决方案:

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也应该使用@" \[email protected]%"代替"\[email protected]%" (循环初始化必须替换为“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文本分配之后。


在迅速,

let myLabel : UILabel!

使您的标签文本适合屏幕,它位于顶部

myLabel.sizeToFit()

使标签字体适合屏幕宽度或特定宽度尺寸。

myLabel.adjustsFontSizeToFitWidth = YES

和一些标签的textAlignment:

myLabel.textAlignment = .center

myLabel.textAlignment = .left

myLabel.textAlignment = .right

myLabel.textAlignment = .Natural

myLabel.textAlignment = .Justified


如果您可以选择创建自己的自定义视图,则可以执行以下操作:

- (void)drawRect:(CGRect)rect
{
    CGRect bounds = self.bounds;
    [self.textColor set];
    [self.text drawInRect:bounds
                 withFont:self.font
            lineBreakMode:UILineBreakModeTailTruncation
                alignment:self.textAlignment];
}

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

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

    [super drawTextInRect:rect];
}

我尝试了涉及换行填充的解决方案,并在某些情况下遇到了错误的行为。 根据我的经验,如上所述,比使用numberOfLines更容易约束绘图rect。

PS你可以想象通过这种方式轻松支持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];
}

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

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


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

您可以使用具有垂直对齐选项的UITextField代替UILabel

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

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

// adjust the height of a multi-line label to make it align vertical with top
+ (void) alignLabelWithTop:(UILabel *)label {
  CGSize maxSize = CGSizeMake(label.frame.size.width, 999);
  label.adjustsFontSizeToFitWidth = NO;

  // get actual height
  CGSize actualSize = [label.text sizeWithFont:label.font constrainedToSize:maxSize lineBreakMode:label.lineBreakMode];
  CGRect rect = label.frame;
  rect.size.height = actualSize.height;
  label.frame = rect;
}

。如何使用? (如果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;
[Utils alignLabelWithTop:lblHello];

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


我在这里提出了建议并创建了一个视图,它可以包装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

我已经使用了很多上面的方法,只想添加一个我用过的快速方法:

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

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

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


我很长时间都在努力解决这个问题,我想分享我的解决方案。

这将为您提供一个UILabel ,它将文本自动收缩到0.5刻度并垂直居中文本。 Storyboard / IB中也提供了这些选项。

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

我知道这是一个旧帖子,但垂直对齐文本是一个巨大的问题(至少对我来说是这样),我想我应该分享这个解决方案,因为我自己找不到一个。

在我看来,使用drawRect有点贵。使UILabel垂直对齐的正确方法是不使用UILabel。使用UITextView(多行UITextField)并观察内容属性,如下所示:

- (UITextView*)textView{
     if(!_textView){
        UIEdgeInsets insets = UIEdgeInsetsMake(0, 50, 0, 5);
        CGRect frame = CGRectMake(0.0f, 0.0f, 100.0f, 100.0f);
        _textView = [[UITextView alloc]initWithFrame:UIEdgeInsetsInsetRect(frame, insets)];
        _textView.delegate = self;
        _textView.scrollEnabled = YES;
        _textView.bounces = YES;
        _textView.backgroundColor = [UIColor whiteColor];
        [_textView setUserInteractionEnabled:NO];
        [_textView addObserver:self forKeyPath:@"contentSize" options:(NSKeyValueObservingOptionNew) context:NULL];
    }
    return _textView;
}

 -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:    (NSDictionary *)change context:(void *)context {
UITextView *tv = object;

CGFloat height = [tv bounds].size.height;
CGFloat contentheight;

#ifdef __IPHONE_7_0
    contentheight = [tv sizeThatFits:CGSizeMake(tv.frame.size.width, FLT_MAX)].height;
#else
    contentheight = [tv contentSize].height;
#endif

    switch(self.verticalAlignment) {
        case VerticalAlignmentBottom:{
            CGFloat topCorrect = ([tv bounds].size.height - contentheight);
            topCorrect = (topCorrect <0.0 ? 0.0 : topCorrect);
            tv.contentOffset = (CGPoint){.x = 0, .y = -topCorrect};
        }
        break;
        case VerticalAlignmentMiddle:{
            CGFloat topCorrect = (height - contentheight * [tv zoomScale])/2.0;
            topCorrect = ( topCorrect < 0.0 ? 0.0 : topCorrect );
            tv.contentOffset = (CGPoint){.x = 0, .y = -topCorrect};
        }
            break;
        case VerticalAlignmentTop:{
            tv.contentOffset = (CGPoint){.x = 0, .y = 0 };
        }
            break;
        default:
            break;
    }
}

基本上这里发生的是我们设置我们作为观察者的类,使用NSKeyValueObservingOptionNew选项查看contentSize属性,因此每次内容更改时,-(void)observeValueForKeyPath:ofObject:change:context:都会调用,然后您可以计算偏移大小以适当地对齐文本。

我不能相信这一点,最初的想法来自here。但是,这个解决方案在iOS7上不起作用。在SO周围拖了几个小时之后,我发现了这个:iOS 7垂直对齐修复。关键在于contentheight = [tv sizeThatFits:CGSizeMake(tv.frame.size.width, FLT_MAX)].height; 。出于某些原因,在iOS 7中,获取contentSize高度不起作用,但修复了它。这两种解决方案都不能单独工作,但经过一点修改后,我能够将上述解决方案合成在一起。


无法在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后忽略NSLineBreakByTruncatingTail (默认值),其他两种截断模式(head和middle)也是如此。 NSLineBreakByClipping也被忽略。 NSLineBreakByCharWrapping像往常一样工作。 框架宽度仍然缩小以适合最右边的字母。

Mark Amery在评论中使用自动布局修复了NIB和故事板:

如果您的标签作为使用autolayout的ViewController视图的子视图包含在nib或storyboard中,那么将sizeToFit调用放入viewDidLoad将不起作用,因为autolayout会在调用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;

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

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

此解决方案不适用于所有人 - 特别是,如果您仍希望在字符串末尾显示“...”,如果它超出您显示的行数,则需要使用其中一个更长的代码 - 但在很多情况下,这将为您提供所需的。


在Interface Builder中

  • UILabel设置为最大可能文本的大小
  • 在Attributes Inspector中将Lines设置为'0'

在你的代码中

  • 设置标签的文本
  • 在您的标签上调用sizeToFit

代码片段:

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

只要您没有执行任何复杂的任务,您就可以使用UITextView而不是UILabels

禁用滚动。

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





text-alignment