Вертикально выровнять UILabel

Я пытаюсь вертикально выровнять текст в UILabel ни моего приложения. Проблема в том, что я хочу, чтобы текст был вертикально выровнен сверху, а размер метки был 280 x 150. Я могу достичь только одной из этих двух вещей. Если я удалю строку

[myLabel sizeToFit];

тогда выравнивание текста в порядке, но размер перепутан. Но если я добавлю вышеуказанную строку, то выравнивание испорчено, но размер в порядке. Как это исправить проблема.

я добавил ниже код -

CGRect labelFrame = CGRectMake(22, 50, 280, 150);
UILabel *myLabel = [[UILabel alloc] initWithFrame:labelFrame];
[myLabel setText:finalRecipe];
[myLabel setBackgroundColor: [UIColor lightGrayColor]];
[myLabel setNumberOfLines:0];
[myLabel sizeToFit];
[self.view addSubview:myLabel];

8 ответов


одной из особенностей FXLabel является то, что она уважает свойство uicontentmode метки, как установлено в Interface builder. Это означает, что вы можете установить метку.contentMode = UIViewContentModeTop; для выравнивания текста в верхней части представления метки (что не работает для обычной UILabel). Этот пример здесь:

https://github.com/nicklockwood/FXLabel/tree/master/Examples/Text%20Alignment

FXLabel-это подкласс UILabel, поэтому я думаю, что это довольно хорошее решение для поставленного вопроса. Однако, если плакат скорее решит проблему, не используя стороннюю библиотеку (что понятно), то вот код для этого:

CGRect labelFrame = CGRectMake(22, 50, 280, 150);
UILabel *myLabel = [[UILabel alloc] initWithFrame:labelFrame];
[myLabel setText:finalRecipe];
[myLabel setBackgroundColor: [UIColor lightGrayColor]];
[myLabel setNumberOfLines:0];

CGFloat fontSize = 0.0f;
labelFrame.size = [myLabel.text sizeWithFont:myLabel.font
                                minFontSize:myLabel.minimumFontSize
                             actualFontSize:&fontSize
                                   forWidth:labelFrame.width
                            lineBreakMode:myLabel.lineBreakMode];

myLabel.frame = labelFrame;
[self.view addSubview:myLabel];

Примечание: (это непроверено, поэтому извиняюсь, если есть какие-то опечатки)


не используйте UILabel для этого. Использовать UIButton С UserInteractionEnabled = NO; и у этого есть опции для вертикального или горизонтального выравнивания текста внутри него.

здесь вы идете:

Свифт:

btnDetail.titleLabel?.numberOfLines = 5
btnDetail.titleLabel?.lineBreakMode = .byCharWrapping
btnDetail.contentVerticalAlignment = .top
btnDetail.contentHorizontalAlignment = .left
btnDetail.isUserInteractionEnabled = false
btnDetail.autoresizesSubviews = true
btnDetail.autoresizingMask = .flexibleWidth

Obj-C

[btnDetail.titleLabel setNumberOfLines:5];
[btnDetail.titleLabel setLineBreakMode:NSLineBreakByCharWrapping];
[btnDetail setContentVerticalAlignment:UIControlContentVerticalAlignmentTop];
[btnDetail setContentHorizontalAlignment:UIControlContentHorizontalAlignmentLeft];
[btnDetail setUserInteractionEnabled:NO];
btnDetail.autoresizesSubviews = YES;
btnDetail.autoresizingMask = UIViewAutoresizingFlexibleWidth;

вам нужно подкласс UILabel. Попробуйте это:

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

    [super drawTextInRect:rect];
}

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

вы даже можете поддержать игнорируемый (вздох) contentMode вот так:

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

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


в Swift, решение JRC подклассов UILabel переопределение drawTextInRect и в соответствии с UIViewContentMode будет выглядеть так:

class AlignableUILabel: UILabel {

    override func drawText(in rect: CGRect) {

        var newRect = CGRect(x: rect.origin.x,y: rect.origin.y,width: rect.width, height: rect.height)
        let fittingSize = sizeThatFits(rect.size)

        if contentMode == UIViewContentMode.top {
            newRect.size.height = min(newRect.size.height, fittingSize.height)
        } else if contentMode == UIViewContentMode.bottom {
            newRect.origin.y = max(0, newRect.size.height - fittingSize.height)
        }

        super.drawText(in: newRect)
    }

}

реализация-это просто:

yourLabel.contentMode = UIViewContentMode.top

для меня это сработало как шарм.


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

установите количество строк в 0, затем вызовите sizeToFit.

[label setNumberOfLines:0];
[label sizeToFit];

подробнее здесь, как я думаю, кто-то еще связан с:вертикально выровнять текст сверху в UILabel


вы можете сделать это с ограничением на построитель интерфейса.

  1. поместите количество строк, которые вы хотите
  2. создайте ограничение с высотой, достаточной для 3 строк, и в разделе отношения поставьте "меньше или равно".

надеюсь, это поможет вам !


Я сделал это, что вы хотите, реализовав категорию:

.h

@interface UILabel (VerticalAlign)
- (void)alignTop;
- (void)alignBottom;
@end

@implementation UILabel (VerticalAlign)

#pragma mark
#pragma mark - Align Methods

- (void)alignTop
{
    [self setFrame:[self newLabelFrame:UIControlContentVerticalAlignmentTop]];
}

- (void)alignBottom
{
    [self setFrame:[self newLabelFrame:UIControlContentVerticalAlignmentBottom]];
}

#pragma mark
#pragma mark - Helper Methods

- (CGRect)newLabelFrame:(UIControlContentVerticalAlignment)alignment
{
    CGRect labelRect = self.frame;

    NSStringDrawingOptions options = NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesFontLeading;

    CGRect textRect = [self.text boundingRectWithSize:CGSizeMake(227.f, CGFLOAT_MAX)
                                              options:options
                                           attributes:@{NSFontAttributeName:self.font}
                                              context:nil];

    CGFloat textOffset = labelRect.size.height - textRect.size.height;

    UIEdgeInsets contentInsets;
    if (alignment == UIControlContentVerticalAlignmentTop)
    {
        if (textOffset < (labelRect.size.height/2.f))
        {
            contentInsets = UIEdgeInsetsMake(-textOffset, 0.f, 0.f, 0.f);
        }
        else
        {
            contentInsets = UIEdgeInsetsMake(0.f, 0.f, textOffset, 0.f);
        }
    }
    else
    {
        if (textOffset < (labelRect.size.height/2.f))
        {
            contentInsets = UIEdgeInsetsMake(0.f, 0.f, -textOffset, 0.f);
        }
        else
        {
            contentInsets = UIEdgeInsetsMake(textOffset, 0.f, 0.f, 0.f);
        }
    }

    return UIEdgeInsetsInsetRect(labelRect, contentInsets);
}

@end

помните, что вам нужно установить "NumberOfLines" в 0. Этот пример работает с параметрами multilines!

после реализации выше категории, вы можете просто сделать:

[myLabel setText:finalRecipe];
[myLabel alignTop];

Ура!


вы можете сделать это следующим образом.......

  1. установите метку numberOfLines свойство 0 из IB

  2. установите метку lineBreakMode as UILineBreakModeWordWrap (очень важно)

теперь все, что вы установили на этикетке, просто добавьте к нему несколько @"\n"..... бывший.-

[yourTextLabel setText:@"myLabel\n\n\n\n\n"];