Выровнять текст по вертикали внутри UILabel - PullRequest
2098 голосов
/ 28 июня 2009

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

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

image representing a UILabel with vertically-centered text

Ответы [ 48 ]

4 голосов
/ 08 марта 2018

(по состоянию на 7 марта 2018 г.)

Swift 4

let maxFrameHeight = 75

myLabel = UILabel()
myLabel.frame = CGRect(x: 9, y: 9, width: 126, height: maxFrameHeight)
myLabel.text = "my labels text displayed"
myLabel.numberOfLines = 0

myLabel.sizeToFit()
let newFrameHeight = myLabel.frame.size.height
let safeNewHeight = min(newFrameHeight, maxFrameHeight)

myLabel.frame = CGRect(x: 9, y: 9, width: 126, height: safeNewHeight)

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

3 голосов
/ 15 марта 2013

Вместо использования sizeToFit вы можете вручную изменить высоту этикетки;

CGSize size = [descLabel.text sizeWithFont:descLabel.font constrainedToSize:CGSizeMake(labelWidth, labelHeight)];
CGRect frame = descLabel.frame;
frame.size.height = size.height;    
[yourLabel setFrame:frame];

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

3 голосов
/ 25 марта 2013

Этот код помогает вам выровнять текст по верху, а также сделать высоту надписи для фиксированного содержимого текста.

инструкция по использованию кода ниже

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

#import "DynamicHeightLable.h"

@implementation DynamicHeightLable
@synthesize isHeightToChange;
- (id)initWithFrame:(CGRect)frame 
{
    self = [super initWithFrame:frame];
    if (self)
    {
        // Initialization code.
        self.isHeightToChange=FALSE;//default

    }
    return self;
}
- (void)drawTextInRect:(CGRect)rect
{
    if(!isHeightToChange){
    CGSize maximumLabelSize = CGSizeMake(self.frame.size.width,2500);

    CGFloat height = [self.text sizeWithFont:self.font
                           constrainedToSize:maximumLabelSize
                               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];

}
- (void) layoutSubviews
{
    [super layoutSubviews];
       if(isHeightToChange){
     CGRect ltempFrame = self.frame;
    CGSize maximumLabelSize = CGSizeMake(self.frame.size.width,2500);

    CGFloat height = [self.text sizeWithFont:self.font
                           constrainedToSize:maximumLabelSize
                               lineBreakMode:self.lineBreakMode].height;
    if (self.numberOfLines != 0) {
        height = MIN(height, self.font.lineHeight * self.numberOfLines);
    }
    ltempFrame.size.height = MIN(ltempFrame.size.height, height);

    ltempFrame.size.height=ltempFrame.size.height;
    self.frame=ltempFrame;
       }
}
@end
2 голосов
/ 31 января 2013

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

.h

@interface VAlignLabel : UILabel
@property (nonatomic, assign) WBZVerticalAlignment alignment;
@end


.m

 -(void)setAlignment:(WBZVerticalAlignment)alignment{

    _alignment = alignment;

    CGSize s = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(self.frame.size.width, 9999) lineBreakMode:NSLineBreakByWordWrapping];

    switch (_alignment)
    {
        case wbzLabelAlignmentVerticallyTop:
            self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width, s.height);
            break;
        case wbzLabelAlignmentVerticallyMiddle:
            self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y + (self.frame.size.height - s.height)/2, self.frame.size.width, s.height);
            break;
        case wbzLabelAlignmentVerticallyBottom:
            self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y + (self.frame.size.height - s.height), self.frame.size.width, s.height);
            break;
        default:
            break;
    }
}

-(void)layoutSubviews{
    [self setAlignment:self.alignment];
}
1 голос
/ 26 июня 2017

Простое решение этой проблемы ...

Поместите UIStackView ниже ярлыка.

Затем используйте AutoLayout, чтобы установить нулевой вертикальный интервал для метки и ограничить верхнюю часть тем, что ранее было нижней меткой. Метка не будет расти, stackView будет. Что мне нравится в этом, так это то, что представление стека не рендеринг. Так что не стоит тратить время на рендеринг. Даже при том, что это делает вычисления AutoLayout.

Возможно, вам придется поиграть с ContentHugging и Resistance, но это также просто.

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

0 голосов
/ 31 января 2019

Это можно сделать с большей гибкостью, установив height constraint для метки в Интерфейсном Разработчике, привязав его к коду с помощью IBOutlet и изменив эту высоту, чтобы текст отображался в конкретной вертикальной позиции. Пример для выравнивания по центру и снизу:

labelHeightConstraint.constant = centerAlignment ? 30 : 15
layoutIfNeeded()
0 голосов
/ 11 ноября 2012

Попробуй это !! Слишком ручной, но прекрасно работает для меня.

[labelName setText:@"This is just a demo"];

NSMutableString *yourString1= @"This is just a demo";


// breaking string
labelName.lineBreakMode=UILineBreakModeTailTruncation;
labelName.numberOfLines = 3;


CGSize maximumLabelSize1 = CGSizeMake(276,37); // Your Maximum text size

CGSize expectedLabelSize1 = [yourString1 sizeWithFont:labelName.font
                                    constrainedToSize:maximumLabelSize1
                                        lineBreakMode:labelName.lineBreakMode];

[labelName setText:yourString1];


CGRect newFrame1 = labelName.frame;
if (expectedLabelSize1.height>=10)
{
    newFrame1.size.height = expectedLabelSize1.height;
}

labelName.frame = newFrame1;
0 голосов
/ 27 октября 2017

Вот решение в 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
}
...