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

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


当前回答

在swift中,

let myLabel:UILabel!

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

myLabel.sizeToFit()

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

myLabel.adjustsFontSizeToFitWidth=是

以及标签的一些文本对齐:

myLabel.textAlignment=.center

myLabel.textAlignment=左侧

myLabel.textAlignment=右侧

myLabel.textAlignment=.自然

myLabel.textAlignment=两端对齐

其他回答

这是一个旧的解决方案,在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

Swift 4.0中有一个解决方案:

func viewDidLoad() {

    super.viewDidLoad()

    // 20 point top and left margin. Sized to leave 20 pt at right.
    let labelFrame = CGRect(x: 20, y: 20, width: 280, height: 150)
    let myLabel = UILabel(frame: labelFrame)
    myLabel.backgroundColor = UIColor.orange

    let labelText = "I am the very model of a modern Major-General, 
    I've information vegetable, animal, and mineral"
    myLabel.text = labelText

    // Tell the label to use an unlimited number of lines
    myLabel.numberOfLines = 0
    myLabel.sizeToFit()

    view.addSubview(myLabel) // add label
}

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

or

[myLabel alignBottom];

创建新类

标签顶部对齐

.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

Edit

下面是一个更简单的实现,它也做到了这一点:

#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

FXLabel(在github上)通过将label.contentMode设置为UIViewContentModeTop来实现这一点。这个组件不是我制造的,但它是我经常使用的组件,具有大量的功能,而且似乎工作得很好。