Вопрос по text-alignment, cocoa-touch, ios, uilabel, uikit – Выровнять текст по вертикали внутри UILabel

2064

у меня естьUILabel с местом для двух строк текста. Иногда, когда текст слишком короткий, этот текст отображается в вертикальном центре метки.

Как выровнять текст по вертикали, чтобы всегда быть в верхней частиUILabel?

image representing a UILabel with vertically-centered text

Ваш Ответ

30   ответов
89

@interface MFTopAlignedLabel : UILabel

@end


@implementation MFTopAlignedLabel

- (void)drawTextInRect:(CGRect) rect
{
    NSAttributedString *attributedText = [[NSAttributedString alloc]     initWithString:self.text attributes:@{NSFontAttributeName:self.font}];
    rect.size.height = [attributedText boundingRectWithSize:rect.size
                                            options:NSStringDrawingUsesLineFragmentOrigin
                                            context:nil].size.height;
    if (self.numberOfLines != 0) {
        rect.size.height = MIN(rect.size.height, self.numberOfLines * self.font.lineHeight);
    }
    [super drawTextInRect:rect];
}

@end

Без суеты, без Objective-c, без суеты, кроме Swift 3:

class VerticalTopAlignLabel: UILabel {

    override func drawText(in rect:CGRect) {
        guard let labelText = text else {  return super.drawText(in: rect) }

        let attributedText = NSAttributedString(string: labelText, attributes: [NSFontAttributeName: font])
        var newRect = rect
        newRect.size.height = attributedText.boundingRect(with: rect.size, options: .usesLineFragmentOrigin, context: nil).size.height

        if numberOfLines != 0 {
            newRect.size.height = min(newRect.size.height, CGFloat(numberOfLines) * font.lineHeight)
        }

        super.drawText(in: newRect)
    }

}

Swift 4.2

class VerticalTopAlignLabel: UILabel {

    override func drawText(in rect:CGRect) {
        guard let labelText = text else {  return super.drawText(in: rect) }

        let attributedText = NSAttributedString(string: labelText, attributes: [NSAttributedString.Key.font: font])
        var newRect = rect
        newRect.size.height = attributedText.boundingRect(with: rect.size, options: .usesLineFragmentOrigin, context: nil).size.height

        if numberOfLines != 0 {
            newRect.size.height = min(newRect.size.height, CGFloat(numberOfLines) * font.lineHeight)
        }

        super.drawText(in: newRect)
    }

}
Быстрая версия работала для меня без каких-либо побочных эффектов! Отличная работа!
Вероятно, лучший ответ здесь, работает во всех сценариях. sizeToFit не работает, если метка находится в UITableviewCell. Хорошая работа.
36

Storyboard solution: Label вStackView и настройка StackViewAxis вHorizontal, Alignment вTop вAttribute Inspector из раскадровки.

enter image description here

Супер полезно. Спасибо!
ГЕНИЙ! Спасибо
Лучший вариант, спасибо Биаг
Это была огромная помощь, спасибо. Лучшее решение для раскадровки здесь на сегодняшний день.
Лучшее решение. Спасибо
7

let myLabel : UILabel!

Чтобы ваш текст метки помещался на экране, и он находился сверху

myLabel.sizeToFit()

Чтобы ваш шрифт метки соответствовал ширине экрана или конкретному размеру ширины.

myLabel.adjustsFontSizeToFitWidth = YES

и немного textAlignment для метки:

myLabel.textAlignment = .center

myLabel.textAlignment = .left

myLabel.textAlignment = .right

myLabel.textAlignment = .Natural

myLabel.textAlignment = .Justified

Просто изменение синтаксиса от старого синтаксиса[myLabel sizeToFit], Спасибо!
133

если это кому-нибудь поможет, у меня возникла та же проблема, но я смог решить ее, просто переключившись с использования.UILabel использоватьUITextView, Я ценю это не для всех, потому что функциональность немного отличается.

Если вы переключитесь на использованиеUITextView, вы можете отключить все свойства просмотра прокрутки, а также включить взаимодействие с пользователем ... Это заставит его действовать больше как ярлык.

enter image description here

Не уверен, как это повлияет на производительность, если многие UILabel преобразуются в текстовые представления.
Это обходной путь, он все еще нуждается в некоторых корректировках, чтобы он выглядел аутентично, но на самом деле это самое простое решение без кода, которое я когда-либо видел.
Все остальные решения в этой теме не работали для меня в iOS 7 (по любой причине). Но просто используяUITextView дал мне желаемый результат сразу.
Небольшой недостаток этого метода заключается в том, что он привнесет в текст дополнительные внутренние отступы. Быстрое решение состоит в том, чтобы ввести отрицательное ограничение.
Мне нравится это решение. Конечно, могут быть проблемы с производительностью, и, например, для простой метки на относительно простом представлении это было идеально для того, что мне нужно (и я не могу заметить какого-либо влияния на производительность)
323

Set the new text:

myLabel.text = @"Some Text"

Set the maximum number of lines to 0 (automatic):

myLabel.numberOfLines = 0

Set the frame of the label to the maximum size:

myLabel.frame = CGRectMake(20,20,200,800)

Call sizeToFit to reduce the frame size so the contents just fit:

[myLabel sizeToFit]

Рамка для надписей теперь достаточно высокая и достаточно широкая, чтобы вместить ваш текст. Верхний левый должен быть неизменным. Я проверил это только с выравниванием по левому верхнему краю текста. Для других выравниваний вам, возможно, придется изменить кадр позже.

Кроме того, на моем ярлыке включена перенос слов.

у меня отлично работает, после установки количества строк в Аттр. Инспектор
Привет, Бен, я только что снова посмотрел свой старый код и обновил свой ответ, указав правильные шаги.
Это не работает, когда вы хотите метку из двух строк, но текст требует больше строк.
Не работает при количестве строк более 1
Это работало нормально для меня. Я установил размеры моей UILabel и изменил numberOfLines на 0 в IB, а затем после установки текста с именем [myLabel sizeToFit].
13

FXLabel (на github) делает это из коробки, установивlabel.contentMode вUIViewContentModeTop, Этот компонент сделан не мной, но это компонент, который я часто использую, имеет множество функций и, кажется, работает хорошо.

14

описанных выше, и просто хочу добавить быстрый и грязный подход, который я использовал:

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

Убедитесь, что количество новых строк в строке приведет к тому, что любой текст заполнит доступное вертикальное пространство, и настройте UILabel для усечения любого переполненного текста.

Because sometimes good enough is good enough.

Примечание: «быстро и грязно» не "идеальное решение для всех времен". Просто скажи.
Однако, учитывая различия в высоте размера экрана на устройствах iOS, в этом случае потребуется переменное число \ n ". для учета изменения высоты кузова (это возможно). Таким образом, этот метод не особенно полезен в долгосрочной перспективе.
@CodeRoadie Быстрый и грязный сделал свое дело для меня, у меня было несколько проблем с версткой с реальным ответом. Я мог бы сделать это «правильным способом», но спасибо, что сэкономили мне время!
Что-то я узнал недавно, когда динамически загружалUITextView это то, что он может вызватьdlopen для поддержки ввода текста. Это может вызвать значительное отставание в потоке пользовательского интерфейса, поэтому этот подход гораздо более производительный!
@dGambit, пожалуйста, обратите внимание: & quot; быстро иdirty& Quot;
7

UITextView вместоUILabels.

Отключить прокрутку.

Если вы хотите, чтобы текст отображался полностью только пользователемsizeToFit а такжеsizeThatFits: методы

14

которая могла бы иметь несколько строк, минимальный размер шрифта и центрироваться как по горизонтали, так и по вертикали в родительском представлении. Я добавил мой ярлык программно на мой взгляд:

- (void) customInit {
    // Setup label
    self.label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
    self.label.numberOfLines = 0;
    self.label.lineBreakMode = UILineBreakModeWordWrap;
    self.label.textAlignment = UITextAlignmentCenter;

    // Add the label as a subview
    self.autoresizesSubviews = YES;
    [self addSubview:self.label];
}

И тогда, когда я хотел изменить текст моего ярлыка ...

- (void) updateDisplay:(NSString *)text {
    if (![text isEqualToString:self.label.text]) {
        // Calculate the font size to use (save to label's font)
        CGSize textConstrainedSize = CGSizeMake(self.frame.size.width, INT_MAX);
        self.label.font = [UIFont systemFontOfSize:TICKER_FONT_SIZE];
        CGSize textSize = [text sizeWithFont:self.label.font constrainedToSize:textConstrainedSize];
        while (textSize.height > self.frame.size.height && self.label.font.pointSize > TICKER_MINIMUM_FONT_SIZE) {
            self.label.font = [UIFont systemFontOfSize:self.label.font.pointSize-1];
            textSize = [ticker.blurb sizeWithFont:self.label.font constrainedToSize:textConstrainedSize];
        }
        // In cases where the frame is still too large (when we're exceeding minimum font size),
        // use the views size
        if (textSize.height > self.frame.size.height) {
            textSize = [text sizeWithFont:self.label.font constrainedToSize:self.frame.size];
        }

        // Draw 
        self.label.frame = CGRectMake(0, self.frame.size.height/2 - textSize.height/2, self.frame.size.width, textSize.height);
        self.label.text = text;
    }
    [self setNeedsDisplay];
}

Надеюсь, что это помогает кому-то!

26

чтобы прочитать код, а также код на введенной странице, и обнаружил, что все они пытаются изменить размер кадра метки, чтобы по умолчанию вертикальное выравнивание по центру не появлялось.

Однако в некоторых случаях мы хотим, чтобы метка занимала все эти пробелы, даже если метка имеет так много текста (например, несколько строк с одинаковой высотой).

Здесь я использовал альтернативный способ ее решения, просто добавив новые строки до конца метки (пожалуйста, обратите внимание, что я на самом деле унаследовалUILabel, но это не обязательно)

CGSize fontSize = [self.text sizeWithFont:self.font];

finalHeight = fontSize.height * self.numberOfLines;
finalWidth = 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 "];
}
32

Vertical Alignment of UILabel is to be set from StoryBoard by Changing the properties noOfLines= 0` и

Constraints

Adjusting UILabel LefMargin, RightMargin and Top Margin Constraints.

Change Content Compression Resistance Priority For Vertical=1000` So that Vertical>Horizontal .

Constraints of UILabel

Edited:

noOfLines=0

и следующих ограничений достаточно для достижения желаемых результатов.

enter image description here

Это было потрясающе. Не могли бы вы объяснить, почему вертикальный> горизонтальный сделал свою работу? Благодарю.
155

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

Требуется дополнительное место в каждой добавленной новой строке, потому что iPhoneUILabels& APOS; в конце концов, возврат каретки игнорируется :(

Аналогично, 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(f,inalWidth, 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.

Дал упор. но это не сработает, если вы не знаете количество строк, что является недостатком
У меня есть строки, равные 2, но это не имеет значения для alignTop или alignBottom, что-то я пропустил? label = [[UILabel alloc] init]; label.numberOfLines = 2; label.frame = CGRectMake (0, TABS_HEIGHT-25, self.frame.size.width, 25); label.font = [UIFont fontWithName: @ & quot; Arial & quot; размер: 10]; label.textAlignment = UITextAlignmentCenter; [label alignTop];
Я хочу показать 3 строки текста и выровнять текст по верху. Итак, могу ли я установить количество строк равным 3. Когда я установлю его на 3, я "вижу" ... " если текст меньше (умещается в одну строку). Как избежать этого & quot; ... & quot;
Удивительно, но я не знал о категориях, это дает мне еще большую оценку языка Objective-c. Изучение большего количества языков так важно, чтобы стать хорошим программистом.
@ D.S. Я заметил, что вы добавляетеVerticalAlign между круглыми скобками после@implementation UILabel, Будучи новичком в Objective-C, я раньше не сталкивался с этим синтаксисом. Как это называется?
6

вы можете сделать что-то вроде этого:

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

textRect(forBounds:limitedToNumberOfLines:).

class TopAlignedLabel: UILabel {
    override func drawText(in rect: CGRect) {
        let textRect = super.textRect(forBounds: bounds, limitedToNumberOfLines: numberOfLines)
        super.drawText(in: textRect)
    }
}
Вы, сэр, бог!
Этот ответ должен получитьway больше голосов, поскольку это, безусловно, самое хорошее и чистое решение!
33

// 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

Как обсуждалосьВот.

27

// 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;
}

& # xFF0E; Как использовать? (Если lblHello создан Интерфейсным Разработчиком, поэтому я пропущу некоторые детали атрибутов 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=2819

11

кто читает это, потому что текст внутри вашего ярлыка не центрирован по вертикали, имейте в виду, что некоторые типы шрифтов не разработаны одинаково. например, если вы создадите метку с размером zapfino 16, вы увидите, что текст не идеально отцентрирован по вертикали.

тем не менее, работа с helvetica будет центрировать ваш текст по вертикали.

Многие пользовательские шрифты не выровнены по вертикали. UILabel или UITextView всегда выровнены по центру по вертикали. Не нужно думать о вертикальном выравнивании в программировании iOS.
10

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

    [super drawTextInRect:rect];
}

Я попробовал решение, включающее заполнение новой строки и столкнулся с неправильным поведением в некоторых случаях. Из моего опыта легче ограничить рисование прямоугольника, как указано выше, чем связываться сnumberOfLines.

Постскриптум Вы можете легко представить поддержку 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];
}
6

намически изменять высоту метки, используяsizeWithFont: методNSStringи просто установите его х и у, как вы хотите.

Ты можешь использоватьUITextField, ПоддерживаетcontentVerticalAlignment peoperty как это подклассUIControl, Вы должны установить егоuserInteractionEnabled НЕТ, чтобы запретить пользователю печатать текст на нем.

59

UILabel вы можете использоватьUITextField который имеет вариант вертикального выравнивания:

textField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
textField.userInteractionEnabled = NO; // Don't allow interaction
Чтобы завершить комментарий @DavidJames: UITextView будет более подходящим
Предостережение: UITextField допускает только одну строку текста.
77

но это было не совсем правильно, или просто вставить в код, поэтому я немного его очистил. Добавьте это расширение либо к собственному файлу .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];
67

я режима прерывания строки UILabel значение «Clip». и добавление фиксированного количества новых строк.

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

Это решение не будет работать для всех, в частности, если вы все еще хотите показать & quot; ... & quot; в конце вашей строки, если она превышает количество строк, которые вы показываете, вам нужно будет использовать один из более длинных фрагментов кода, но во многих случаях это даст вам то, что вам нужно.

и лучше добавить пробелы & quot; \ n \ n & quot;
Установка режима разрыва строки на «клип»; кажется, портит авто-размер этикетки. использованиеUILineBreakModeWordWrap вместо.
14

что ответы на этот вопрос в настоящее время немного устарели, поэтому добавим их для поклонников автоматической верстки.

Авто макет делает этот вопрос довольно тривиальным. Предполагая, что мы добавляем метку вUIView *viewследующий код выполнит это:

UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];
[label setText:@"Some text here"];
[label setTranslatesAutoresizingMaskIntoConstraints:NO];
[view addSubview:label];

[view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[label]|" options:0 metrics:nil views:@{@"label": label}]];
[view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[label]" options:0 metrics:nil views:@{@"label": label}]];

Высота метки будет вычислена автоматически (с ее использованием).intrinsicContentSize) и метка будет располагаться по горизонтали, сверхуview.

10

установите для вертикального contentHuggingPriority значение 1000 в коде или IB. Тогда в IB вам, возможно, придется удалить ограничение высоты, установив его приоритет на 1, а затем удалив его.

48

Это даст вамUILabel это автоматически сократит текст до 0,5 масштаба и по центру текста по вертикали. Эти опции также доступны в раскадровке / IB.

[labelObject setMinimumScaleFactor:0.5];
[labelObject setBaselineAdjustment:UIBaselineAdjustmentAlignCenters];
Он работал как идеально среди всех предоставленных ответов. Спасибо, Дэвид Греко. Наряду с этими свойствами, если мы устанавливаем AdjustmentsFontSizeToFitWidth в значение YES, текст будет помещаться во фрейм без изменения фрейма метки.
38

enter image description here

В Интерфейсном Разработчике

Set UILabel to size of biggest possible Text Set Lines to '0' in Attributes Inspector

В вашем коде

Set the text of the label Call sizeToFit on your label

Фрагмент кода:

self.myLabel.text = @"Short Title";
[self.myLabel sizeToFit];
работал отлично, за исключением того, что в моем случае мне нужно было установить строки на 2 - иметь UILabel внутри UITableViewCell и установить значение 0, чтобы перекрыть его, но установка на 2 работала (ячейка имеет достаточно места для 2 строк)
19

которое может обернуть 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
16

TTTAttributedLabel, он поддерживает вертикальное выравнивание.

@property (nonatomic) TTTAttributedLabel* label;
<...>

//view's or viewController's init method
_label.verticalAlignment = TTTAttributedLabelVerticalAlignmentTop;
42

LabelTopAlign

.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
+1 за реальный ответ. в отличие отsizeToFit Решения это на самом деле делаетUILabel положилany текст вверху, даже если вы динамически заменяете более короткий текст более длинным или наоборот.
2619

UILabel, но вы можете получить тот же эффект, изменив рамку метки. Я сделал свои ярлыки оранжевыми, чтобы вы могли четко видеть, что происходит.

Вот быстрый и простой способ сделать это:

    [myLabel sizeToFit];

sizeToFit to squeeze a label

Если у вас есть метка с более длинным текстом, который будет занимать более одной строки, установитеnumberOfLines в0 (ноль здесь означает неограниченное количество строк).

    myLabel.numberOfLines = 0;
    [myLabel sizeToFit];

Longer label text with sizeToFit

Longer Version

Я сделаю свою метку в коде, чтобы вы могли видеть, что происходит. Вы можете настроить большую часть этого в Интерфейсном Разработчике также. Моя настройка - приложение на основе вида с фоновым изображением, которое я сделал в 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];

enter image description here

Ярлык по-прежнему имеет фиксированный верхний левый угол. Вы можете сохранить ширину оригинальной метки в переменной и установить ее после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;

label alignment

Обратите внимание, чтоsizeToFit будет уважать минимальную ширину вашей первоначальной метки. Если вы начнете с метки шириной 100 и позвонитеsizeToFit на нем он вернет вам (возможно, очень высокий) ярлык шириной 100 (или чуть меньше). Возможно, вы захотите установить метку на минимальную ширину, которую вы хотите, перед изменением размера.

Correct label alignment by resizing the frame width

Некоторые другие вещи, чтобы отметить:

Будь тоlineBreakMode зависит от того, как он установлен.NSLineBreakByTruncatingTail (по умолчанию) игнорируется послеsizeToFit, как и два других режима усечения (голова и середина).NSLineBreakByClipping также игнорируется.NSLineBreakByCharWrapping работает как обычно. Ширина рамки все еще сужена, чтобы соответствовать самой правой букве.

Марк Эмери дал исправление для NIB и раскадровок с использованием Auto Layout в комментариях:

If your label is included in a nib or storyboard as a subview of the view of a ViewController that uses autolayout, then putting your sizeToFit call into viewDidLoad won't work, because autolayout sizes and positions the subviews after viewDidLoad is called and will immediately undo the effects of your sizeToFit call. However, calling sizeToFit from within viewDidLayoutSubviews will work.

My Original Answer (for posterity/reference):

Это использует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;
вам нужно удалить autolayout
Если вы используете автоматический макет и раскадровку, добавьте ограничение с параметром & quot; Удалить во время сборки & quot; проверено поможет
Если вам нужно это работать сadjustsFontSizeToFitWidth затем используйте sizeToFit, затем установите для фрейма метки значение 0, 0, theWidthYouWant, label.frame.size.height (которая является новой высотой, определяемой sizeToFit).adjustsFontSizeToFitWidth
Этот ответ неоправданно сложен и использует слово «вокруг». Пожалуйста, ознакомьтесь с предложением простого изменения приоритета вертикального содержимого. Не требует никакого кода ...
Вот простой способ решения проблемы:stackoverflow.com/a/26632490/636559

Похожие вопросы