Вертикально выравнивать текст вверху в UILabel

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

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

image representing a UILabel with vertically-centered text

1886
задан Stefan 28 июня '09 в 11:54
источник поделиться

46 ответов

  • 1
  • 2

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

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

    [myLabel sizeToFit];

sizeToFit to squeeze a label


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

    myLabel.numberOfLines = 0;
    [myLabel sizeToFit];

Longer label text with 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];

enter image description here

Наклейка все еще имеет размер с фиксированным верхним левым углом. Вы можете сохранить исходную ширину меток в переменной и установить ее после sizeToFit или задать фиксированную ширину для устранения этих проблем:

    myLabel.textAlignment = NSTextAlignmentCenter;

    [myLabel setNumberOfLines:0];
    [myLabel sizeToFit];

    CGRect myFrame = myLabel.frame;
    // Resize the frame 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 в комментариях:

Если ваш ярлык включен в ниб или раскадровку в качестве подсмотра view ViewController, который использует автозапуск, то размещение вашего вызова sizeToFit в viewDidLoad не будет работать, поскольку размеры автозапуска и расположение subviews после viewDidLoad вызывается и немедленно отменяет действие вашего вызова sizeToFit. Однако вызов sizeToFit из viewDidLayoutSubviews будет работать.


Мой оригинальный ответ (для потомков/ссылка):

Это использует метод 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;
2499
ответ дан nevan king 28 июня '09 в 13:36
источник поделиться
  • Установите новый текст:

    myLabel.text = @"Some Text"
    
  • Установите maximum number строк в 0 (автоматический):

    myLabel.numberOfLines = 0
    
  • Установите для рамки метки максимальный размер:

    myLabel.frame = CGRectMake(20,20,200,800)
    
  • Вызовите sizeToFit, чтобы уменьшить размер кадра, чтобы содержимое просто соответствовало:

    [myLabel sizeToFit]
    

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

Кроме того, у моей метки включен перенос слов.

307
ответ дан Jakob Egger 27 авг. '10 в 19:24
источник поделиться

Ссылаясь на решение для расширения:

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 также должен быть обновлен с помощью @" \n@%" вместо "\n@%" (для инициализации цикла необходимо заменить на "for (int я = 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.

149
ответ дан Dmitri Sologoubenko 09 сент. '10 в 16:01
источник поделиться

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

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

введите описание изображения здесь

122
ответ дан jowie 05 окт. '11 в 15:46
источник поделиться

Как и в предыдущем ответе, но это было не совсем правильно или легко похлопать по коду, поэтому я немного почистил его. Добавьте это расширение либо к своему собственному файлу .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];
76
ответ дан BadPirate 04 марта '10 в 5:44
источник поделиться

Без суеты, без суеты

@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

Нет muss, no 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)
    }

}
73
ответ дан jasongregori 21 мая '12 в 10:47
источник поделиться

Еще более быстрый (и более грязный) способ выполнить это, установив режим разрыва строки UILabel на "Clip" и добавив фиксированное количество строк новой строки.

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

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

65
ответ дан Purple Ninja Girl 19 апр. '10 в 0:08
источник поделиться

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

textField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
textField.userInteractionEnabled = NO; // Don't allow interaction
56
ответ дан ivanzoid 10 февр. '12 в 13:36
источник поделиться

Я долгое время боролся с этим, и я хотел поделиться своим решением.

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

[labelObject setMinimumScaleFactor:0.5];
[labelObject setBaselineAdjustment:UIBaselineAdjustmentAlignCenters];
46
ответ дан David Greco 16 окт. '12 в 19:38
источник поделиться

Создайте новый класс

LabelTopAlign

.h файл

#import <UIKit/UIKit.h>


@interface KwLabelTopAlign : UILabel {

}

@end

.m file

#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

Изменить

Здесь выполняется более простая реализация, которая делает то же самое:

#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
41
ответ дан sebastian friedrich 04 авг. '11 в 11:07
источник поделиться

enter image description here

В интерфейсе Builder

  • Установите UILabel размер максимально возможного текста
  • Установите Lines в '0' в Инспекторе атрибутов

В вашем коде

  • Установите текст метки
  • Вызов sizeToFit на вашей этикетке

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

self.myLabel.text = @"Short Title";
[self.myLabel sizeToFit];
38
ответ дан bearMountain 03 янв. '12 в 7:40
источник поделиться

Создайте подкласс 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

Как обсуждалось здесь.

33
ответ дан Martin Wickman 14 июля '11 в 17:33
источник поделиться

Я написал функцию утилиты для достижения этой цели. Вы можете посмотреть:

// 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 создается конструктором интерфейса, поэтому я пропускаю некоторые атрибуты атрибутов 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

27
ответ дан firestoke 23 мая '11 в 11:16
источник поделиться

Для Adaptive UI (iOS8 или после) вертикальное выравнивание UILabel должно быть установлено из StoryBoard путем изменения свойств   noOfLines= 0` и

Ограничения

  • Корректировка ограничений UILabel LefMargin, RightMargin и Top Margin.

  • Измените Content Compression Resistance Priority For Vertical= 1000` Чтобы вертикальный > горизонтальный.

Ограничения UILabel

Отредактировано:

noOfLines=0

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

введите описание изображения здесь

26
ответ дан Rabindra Nath Nandi 08 авг. '15 в 8:29
источник поделиться

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

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

Здесь я использовал альтернативный способ его решения, просто добавив новые строки в конец метки (обратите внимание, что я действительно унаследовал 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 "];
}
25
ответ дан Walty Yeung 30 янв. '10 в 9:32
источник поделиться

Я воспользовался этими предложениями и создал представление, которое может обернуть 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
18
ответ дан user486646 14 дек. '10 в 4:27
источник поделиться

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

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

//view or viewController init method
_label.verticalAlignment = TTTAttributedLabelVerticalAlignmentTop;
16
ответ дан Andrew Romanov 28 авг. '14 в 11:50
источник поделиться

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

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

14
ответ дан petehare 29 апр. '14 в 4:21
источник поделиться

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

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

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

13
ответ дан Johnus 14 сент. '10 в 4:14
источник поделиться

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

13
ответ дан jjxtra 27 сент. '13 в 18:35
источник поделиться

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

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

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

Потому что иногда достаточно хорошо.

12
ответ дан Code Roadie 18 сент. '12 в 18:59
источник поделиться

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

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

11
ответ дан Nir Pengas 01 марта '11 в 3:09
источник поделиться

Подкласс UILabel и ограничить прямоугольник рисования, например:

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

    [super drawTextInRect:rect];
}

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

P.S. Вы можете легко представить поддержку 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];
}
10
ответ дан jrc 03 июля '12 в 18:49
источник поделиться

Решение раскадровки: Самый простой и простой способ - вставить Label в StackView и установить StackView Axis на Horizontal, Alignment на Top в Attribute Inspector из раскадровки.

введите описание изображения здесь

8
ответ дан Baig 28 марта '17 в 14:27
источник поделиться

Если вы используете автозапуск, установите вертикальный контентHuggingPriority 1000, либо в коде, либо в IB. В IB вам может потребоваться удалить ограничение по высоте, установив приоритет на 1, а затем удалив его.

8
ответ дан phatmann 05 сент. '13 в 19:38
источник поделиться

Пока вы не выполняете сложную задачу, вы можете использовать UITextView вместо UILabels.

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

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

7
ответ дан thesummersign 12 марта '12 в 21:37
источник поделиться

Это старое решение, используйте автозапуск на iOS >= 6

Мое решение:
1/Разделите строки самостоятельно (игнорируя настройки обертки обложек)
2/Рисовать линии самостоятельно (без учета выравнивания меток)


@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
6
ответ дан Sulthan 28 сент. '11 в 14:46
источник поделиться

Если создание собственного пользовательского представления является опцией, вы можете сделать что-то вроде этого:

- (void)drawRect:(CGRect)rect
{
    CGRect bounds = self.bounds;
    [self.textColor set];
    [self.text drawInRect:bounds
                 withFont:self.font
            lineBreakMode:UILineBreakModeTailTruncation
                alignment:self.textAlignment];
}
6
ответ дан jcjimenez 17 авг. '11 в 0:43
источник поделиться

Swift 2.0:

Сделать постоянными значениями перечисления в пустом файле Swift.

//  AppRef.swift

import UIKit
import Foundation

enum UILabelTextPositions : String {

 case VERTICAL_ALIGNMENT_TOP = "VerticalAlignmentTop"
 case VERTICAL_ALIGNMENT_MIDDLE = "VerticalAlignmentMiddle"
 case VERTICAL_ALIGNMENT_BOTTOM = "VerticalAlignmentBottom"

}

Использование расширения UILabel:

Создайте пустой класс Swift и назовите его. Добавьте следующий

//  AppExtensions.swift

import Foundation
import UIKit

extension UILabel{ 
 func makeLabelTextPosition (sampleLabel :UILabel?, positionIdentifier : String) -> UILabel
 {
  let rect = sampleLabel!.textRectForBounds(bounds, limitedToNumberOfLines: 0)

  switch positionIdentifier
  {
  case "VerticalAlignmentTop":
   sampleLabel!.frame = CGRectMake(bounds.origin.x+5, bounds.origin.y, rect.size.width, rect.size.height)
   break;

  case "VerticalAlignmentMiddle":
   sampleLabel!.frame = CGRectMake(bounds.origin.x+5,bounds.origin.y + (bounds.size.height - rect.size.height) / 2,
    rect.size.width, rect.size.height);
   break;

  case "VerticalAlignmentBottom":
   sampleLabel!.frame = CGRectMake(bounds.origin.x+5, bounds.origin.y + (bounds.size.height - rect.size.height),rect.size.width, rect.size.height);
   break;

  default:
   sampleLabel!.frame = bounds;
   break;
  }
  return sampleLabel!

 }
}

Использование:

myMessageLabel.makeLabelTextPosition(messageLabel, positionIdentifier: UILabelTextPositions.VERTICAL_ALIGNMENT_TOP.rawValue)
5
ответ дан Alvin George 29 марта '16 в 9:16
источник поделиться

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

- (id)init
{
    if (self = [super init]) {
        contentEdgeInsets = UIEdgeInsetsZero;
    }

    return self;
}

- (void)layoutSubviews
{
    CGRect localBounds = self.bounds;
    localBounds = CGRectMake(MAX(0, localBounds.origin.x + contentEdgeInsets.left), 
                             MAX(0, localBounds.origin.y + contentEdgeInsets.top), 
                             MIN(localBounds.size.width, localBounds.size.width - (contentEdgeInsets.left + contentEdgeInsets.right)), 
                             MIN(localBounds.size.height, localBounds.size.height - (contentEdgeInsets.top + contentEdgeInsets.bottom)));

    for (UIView *subview in self.subviews) {
        if ([subview isKindOfClass:[UILabel class]]) {
            UILabel *label = (UILabel*)subview;
            CGSize lineSize = [label.text sizeWithFont:label.font];
            CGSize sizeForText = [label.text sizeWithFont:label.font constrainedToSize:localBounds.size lineBreakMode:label.lineBreakMode];

            NSInteger numberOfLines = ceilf(sizeForText.height/lineSize.height);

            label.numberOfLines = numberOfLines;
            label.frame = CGRectMake(MAX(0, contentEdgeInsets.left), MAX(0, contentEdgeInsets.top), localBounds.size.width, MIN(localBounds.size.height, lineSize.height * numberOfLines)); 
        }
    }
}
5
ответ дан sean woodward 15 дек. '10 в 22:41
источник поделиться
  • 1
  • 2

Другие вопросы по меткам