UILabel 내에서 텍스트를 세로로 정렬


2175

나는이 UILabel두 줄의 텍스트를위한 공간. 때로는 텍스트가 너무 짧은 경우이 텍스트가 레이블의 세로 가운데에 표시됩니다.

텍스트를 항상 맨 위에 오도록 세로로 정렬하려면 어떻게합니까 UILabel?

세로 중심의 텍스트가있는 UILabel을 나타내는 이미지

답변:


2702

에 수직 정렬을 설정하는 방법은 UILabel없지만 레이블의 프레임을 변경하여 동일한 효과를 얻을 수 있습니다. 무슨 일이 일어나고 있는지 명확하게 볼 수 있도록 라벨을 주황색으로 만들었습니다.

이 작업을 수행하는 빠르고 쉬운 방법은 다음과 같습니다.

    [myLabel sizeToFit];

라벨을 짜려면


당신이 한 줄 이상, 세트 것 이상 텍스트 레이블이있는 경우 numberOfLines에을 0(영 여기 라인의 무제한을 의미한다).

    myLabel.numberOfLines = 0;
    [myLabel sizeToFit];

sizeToFit가있는 더 긴 레이블 텍스트


더 긴 버전

진행 상황을 확인할 수 있도록 레이블을 코드로 작성하겠습니다. Interface Builder에서도 대부분을 설정할 수 있습니다. 내 설정은 여백 (20 점)을 표시하기 위해 Photoshop에서 만든 배경 이미지가있는보기 기반 앱입니다. 라벨은 매력적인 주황색이므로 치수가 어떻게 진행되는지 확인할 수 있습니다.

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

여기에 이미지 설명을 입력하십시오

레이블의 크기는 여전히 왼쪽 상단에 고정되어 있습니다. 원래 레이블의 너비를 변수에 저장하고 이후에 설정 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;

라벨 정렬


참고 sizeToFit초기 라벨의 최소 폭을 존중합니다. 너비가 100 인 레이블로 시작하여 호출 sizeToFit하면 너비가 100 (또는 약간 작은) 인 레이블이 다시 제공됩니다. 크기를 조정하기 전에 원하는 최소 너비로 레이블을 설정할 수 있습니다.

프레임 너비를 조정하여 올바른 레이블 정렬

몇 가지 참고할 사항 :

lineBreakMode존중 여부 는 설정 방법에 따라 다릅니다. 다른 두 절단 모드 (헤드 및 중간)와 마찬가지로 NSLineBreakByTruncatingTail(기본값)은 이후 sizeToFit에 무시 됩니다. NSLineBreakByClipping또한 무시됩니다.NSLineBreakByCharWrapping평소와 같이 작동합니다. 프레임 너비는 여전히 가장 오른쪽 글자에 맞게 좁혀집니다.


마크 애 머리 는 주석에서 자동 레이아웃을 사용하여 NIB 및 스토리 보드에 대한 수정 사항을 제공했습니다.

view자동 레이아웃을 사용하는 ViewController 의 하위보기로 레이블이 펜촉 또는 스토리 보드에 포함되어 있으면 자동 레이아웃 크기와 위치 가 호출 된 후 하위보기 가 호출되고 즉시 효과가 취소 되므로 sizeToFit호출 viewDidLoad이 작동하지 않습니다. 요구. 그러나, 호출 내에서 의지 작동합니다.viewDidLoadsizeToFitsizeToFitviewDidLayoutSubviews


내 원래 답변 (후손 / 참조 용) :

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;

10
자동 레이아웃을 제거해야합니다
hungbm06

4
다음은 문제를 해결하는 간단한 방법입니다 : stackoverflow.com/a/26632490/636559
AboulEinein

자동 레이아웃 및 스토리 보드를 사용하는 경우 "빌드 타임에 제거"옵션이 선택된 제약 조건을 추가하면 도움이됩니다.
JK ABC

당신이이 작업을해야하는 경우 adjustsFontSizeToFitWidth다음 sizeToFit 다음 다음 적용 (sizeToFit에 의해 결정 새로운 높이) 0, 0, theWidthYouWant, label.frame.size.height에 라벨의 프레임을 설정 사용adjustsFontSizeToFitWidth
알버트 렌쇼

3
이 답변은 불필요하게 복잡하며 "단어"를 사용하고 있습니다. 단순히 수직 콘텐츠 포옹 우선 순위를 변경하는 제안을 참조하십시오. 어떤 코드가 필요하지 않습니다 ...
beetree

335
  1. 새 텍스트를 설정하십시오.

    myLabel.text = @"Some Text"
  2. maximum number행 수를 0 (자동)으로 설정하십시오 .

    myLabel.numberOfLines = 0
  3. 라벨의 프레임을 최대 크기로 설정하십시오.

    myLabel.frame = CGRectMake(20,20,200,800)
  4. sizeToFit내용물이 잘 맞도록 프레임 크기를 줄이려면 호출하십시오 .

    [myLabel sizeToFit]

레이블 프레임은 이제 텍스트에 맞게 충분히 높고 넓습니다. 왼쪽 상단은 변경되지 않아야합니다. 왼쪽 상단 텍스트로만 테스트했습니다. 다른 정렬의 경우 나중에 프레임을 수정해야 할 수도 있습니다.

또한 내 레이블에는 단어 줄 바꿈이 활성화되어 있습니다.


벤, 나는 방금 이전 코드를 다시 보았고 필요한 올바른 단계로 답변을 업데이트했습니다.
Jakob Egger

이것은 나를 위해 잘 작동했습니다. UILabel의 크기를 설정하고 IB에서 numberOfLines를 0으로 변경 한 다음 [myLabel sizeToFit]라는 텍스트를 설정 한 후
Dan Ellis

Attr에서 줄 수를 설정 한 후 나에게 완벽하게 작동합니다. 인스펙터
d2burke

행 수가 1보다 많은 경우 작동하지 않습니다.
Tom

두 줄의 레이블을 원할 때 작동하지 않지만 텍스트에 더 많은 줄이 필요합니다.
호세 마누엘 아 바카 로드리게스

159

확장 솔루션을 참조하십시오.

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 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(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 텍스트 할당 후.


@DS 다음에 VerticalAlign괄호 사이 에 추가하는 것으로 나타났습니다 @implementation UILabel. Objective-C를 처음 사용하기 전에이 구문을 실행하지 않았습니다. 이것이 무엇입니까?
율리우스

놀랍고 범주에 대해 몰랐기 때문에 Objective-c 언어에 대해 더 감사하게 생각합니다. 좋은 프로그래머가 되려면 더 많은 언어를 배우는 것이 중요합니다.
JeroenEijkhof 8:26에

공감하기. 그러나 단점은 줄 수를 모르면 작동하지 않습니다
Tjirp

3 줄의 텍스트를 표시하고 텍스트를 맨 위에 정렬했습니다. 따라서 줄 수를 3으로 설정해야합니까? 3으로 설정하면 텍스트가 적 으면 (한 줄에 맞는 경우) "..."가 표시됩니다. 이것을 피하는 방법 "..."
Satyam

1
이 카테고리의 수정 사항을 게시했는데 곧 승인 될 것입니다. 메소드 sizeWithFont:constrainedToSize:lineBreakMode:와 sizeWithFont :는 모두 iOS7에서 감가 상각됩니다. 또한이 범주는 numberOfLines가 0보다 큰 경우에만 레이블에서 작동합니다.
timgcarlson

146

누군가에게 도움이되는 경우를 대비하여 동일한 문제가 있었지만 UILabel을 사용 에서 사용 으로 전환하여 문제를 해결할 수있었습니다 UITextView. 기능이 약간 다르기 때문에 모든 사람에게 해당되는 것은 아닙니다.

를 사용으로 전환하면 UITextView모든 스크롤보기 속성과 사용자 상호 작용 활성화됨을 끌 수 있습니다. 그러면 레이블처럼 작동하게됩니다.

여기에 이미지 설명을 입력하십시오


1
많은 UILabels가 텍스트보기로 변환되는 경우 이것이 성능에 어떤 영향을 줄지 잘 모르겠습니다.
ninjaneer

2
이 스레드의 다른 모든 솔루션은 iOS 7에서 어떤 이유로 든 작동하지 않았습니다. 그러나 단순히 a를 사용 UITextView하면 원하는 결과를 즉시 얻을 수 있습니다.
Clifton Labrum

1
해결 방법이지만 여전히 실제처럼 보이기 위해 약간의 조정이 필요하지만 실제로 이것은 내가 본 코드 중 가장 쉬운 코드 솔루션입니다.
Itai Spector

1
나는이 해결책을 좋아한다. 물론 성능 문제가있을 수 있습니다. 비교적 간단한보기의 간단한 레이블에 대해서는 이것이 필요한 것 (성능에 영향을주지 않음)에 완벽했습니다.
JCutting8

1
이 방법의 작은 단점은 텍스트에 추가 고유 패딩을 도입한다는 것입니다. 빠른 수정은 부정적인 제약 조건을 도입하는 것입니다.
Sira Lam

122

무스, 소란 없음

@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, 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)
    }

}

스위프트 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)
    }

}

신속한 버전은 부작용없이 저에게 효과적이었습니다! 훌륭한 일!
l.vasilev

2
아마도 가장 좋은 대답은 모든 시나리오에서 작동합니다. 레이블이 UITableviewCell에 있으면 sizeToFit가 작동하지 않습니다. 잘 했어.
rajat chauhan

79

위의 답변과 같지만 코드에 넣기가 쉽지 않았거나 코드를 작성하기가 쉽지 않았습니다. 이 확장을 자체 .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];

sizeWithFont 지원 중단
tdios

68

UILabel의 줄 바꿈 모드를 "클립"으로 설정하고 고정 된 줄 바꿈을 추가하는 것이 더 빠르고 더 더러운 방법입니다.

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

이 솔루션은 모든 사람에게 적용되지는 않습니다. 특히 문자열 끝에 "..."를 표시하려는 경우 줄 수를 초과하는 경우 계속 표시하려면 다음 중 하나를 사용해야합니다. 더 긴 코드 비트-그러나 많은 경우에 필요한 것을 얻을 수 있습니다.


3
줄 바꿈 모드를 'clip'으로 설정하면 레이블의 자동 크기가 엉망인 것 같습니다. UILineBreakModeWordWrap대신 사용하십시오 .
Niels van der Rest

더 나은 공백을 추가하십시오 "\ n \ n"
djdance

68

스토리 보드를 사용하는 가장 쉬운 방법 :

삽입 라벨StackView 특성 Inspector에서 StackView의 두 가지 특성은 다음과 세트 :

1 Axis~Horizontal ,

2 Alignment~Top

여기에 이미지 설명을 입력하십시오


1
더 나은 결과를 위해 당신이 할 수있는이 StackView>보기> UILabel의, 당신은 단지 StackView, 최소 크기로 UILabel의에 맞게 StackView 크기 조정 내부 UILabel의 포함 할 때 때문에
다니엘 벨트 라미

좋은 장소에 대한 생각 UILabel몇 가지로 UIView서브 클래스 (보통은 UIView일반적으로 충분하다) 아래 방향으로 그 라벨 성장한다하자. 감사!
Viktor Kucera

1
대박! 그것은 당신이 할 필요가 있다고도 언급 할만큼 가치의 명확한 제약 상의 UILabel와 StackView이 일을 할 수 있습니다. 감사!
Luiz Dias

레이블이 선택된 편집기-> 내장 메뉴 명령을 사용하면 레이블 제약 조건이 Xcode에 의해 지워지고 StackView의 제약 조건을 설정할 수 있습니다. 이 접근법은 내가 그것을 발견 한 방법 인 'SwiftUI'레이아웃 접근 방식에 가장 가깝습니다.
로켓 가든

왜 이것이 작동합니까?
Novellizator

60

대신 수직 정렬 옵션이있는 것을 UILabel사용할 수 있습니다 UITextField.

textField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
textField.userInteractionEnabled = NO; // Don't allow interaction

7
주의 사항 : UITextField는 한 줄의 텍스트 만 허용합니다.
David James

2
@DavidJames 의견을 완료하려면 : UITextView가 더 적합합니다
CedricSoubrie

49

나는 오랫동안이 문제로 고생했으며 내 솔루션을 공유하고 싶었습니다.

이렇게하면 UILabel텍스트를 0.5 스케일까지 자동 축소하고 텍스트를 세로로 가운데에 맞출 수 있습니다. 이러한 옵션은 스토리 보드 / IB에서도 사용할 수 있습니다.

[labelObject setMinimumScaleFactor:0.5];
[labelObject setBaselineAdjustment:UIBaselineAdjustmentAlignCenters];

제공된 모든 답변 중 완벽하게 작동했습니다. @David Greco에게 감사합니다. 이러한 속성과 함께 adjustsFontSizeToFitWidth를 YES로 설정하면 레이블의 프레임을 수정하지 않고 텍스트가 프레임에 맞습니다.
Ashok

43

새로운 수업 만들기

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

편집하다

다음은 동일한 작업을 수행하는 간단한 구현입니다.

#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넣어 모든 동적 마찬가지 긴 하나 또는 그와 짧은 텍스트를 교체하는 경우에도, 상단에 텍스트를.
SnakE

38

여기에 이미지 설명을 입력하십시오

인터페이스 빌더에서

  • UILabel가능한 가장 큰 텍스트의 크기로 설정
  • Lines속성 관리자에서 '0'으로 설정

당신의 코드에서

  • 라벨의 텍스트를 설정
  • sizeToFit라벨에 전화

코드 스 니펫 :

self.myLabel.text = @"Short Title";
[self.myLabel sizeToFit];

내 경우에는 줄을 2로 설정해야했습니다 .UITableViewCell 내부에 UILabel이 있고 0으로 설정하면 겹치지 만 2로 설정하면 (셀에 2 줄의 공간이 충분합니다)
eselk

34

적응 형 UI (iOS8 또는 이후)의 경우 속성을 noOfLines= 0 으로 변경하여 스토리 보드에서 UILabel의 세로 맞춤을 설정합니다.

제약

  1. UILabel LefMargin, RightMargin 및 Top Margin 제약 조건 조정.

  2. Content Compression Resistance Priority For VerticalVertical> Horizontal이되도록 = 1000`을 변경하십시오 .

UILabel의 제약

편집 :

noOfLines=0

그리고 다음과 같은 제약은 원하는 결과를 달성하기에 충분합니다.

여기에 이미지 설명을 입력하십시오


대단 했어. 왜 Vertical> Horizontal이 그 일을했는지 ​​설명 할 수 있습니까? 감사.
Gabriel

33

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

여기서 논의한 바와 같이 .


27

이 목적을 달성하기 위해 util 함수를 작성했습니다. 당신은 볼 수 있습니다 :

// 여러 줄 레이블의 높이를 조정하여 위쪽과 수직으로 정렬
+ (void) alignLabelWithTop : (UILabel *) 라벨 {
  CGSize maxSize = CGSizeMake (label.frame.size.width, 999);
  label.adjustsFontSizeToFitWidth = 아니요;

  // 실제 높이를 얻는다
  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;
[alignLabelWithTop : lblHello 활용];

나는 또한 기사로 내 블로그에 썼습니다 : http://fstoke.me/blog/?p=2819


27

소개 된 페이지의 코드뿐만 아니라 코드를 읽는 데 시간이 걸렸으며 기본 중앙 수직 정렬이 나타나지 않도록 레이블의 프레임 크기를 수정하려고 시도했습니다.

그러나 경우에 따라 레이블에 너무 많은 텍스트 (예 : 동일한 높이의 여러 행)가 있더라도 레이블이 해당 공간을 모두 차지하려고합니다.

여기서는 레이블 끝에 줄 바꿈을 추가하여 다른 방법으로 문제를 해결했습니다 (실제로 상속 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 "];
}

22

내 응용 프로그램에서 한 일은 UILabel의 line 속성을 0으로 설정하고 UILabel의 맨 아래 제약 조건을 만들고 아래 이미지와 같이> = 0으로 설정되어 있는지 확인하는 것이 었습니다. 여기에 이미지 설명을 입력하십시오


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

19

TTTAttributedLabel 을 사용할 수 있으며 세로 정렬을 지원합니다.

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

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

16

이 질문에 대한 답변이 약간 오래되어서 자동 레이아웃 팬을 위해 추가했습니다.

자동 레이아웃은이 문제를 매우 사소한 것으로 만듭니다. 에 레이블을 추가한다고 가정하면 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됩니다.


15

위의 많은 방법을 사용했으며, 내가 사용한 빠르고 더러운 접근법을 추가하고 싶습니다.

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

문자열의 줄 바꿈 수에 따라 텍스트가 사용 가능한 수직 공간을 채우고 UILabel이 오버플로 된 텍스트를 자르도록 설정하십시오.

때때로 충분하면 충분 합니다.


그러나 iOS 장치의 화면 크기 높이가 다르면 uilabel 높이 변경을 설명하기 위해 변수 수 '\ n'이 필요합니다 (가능한 경우). 따라서이 방법은 특히 유용하지 않습니다.
Rambatino

참고 : "빠르고 더러운"은 "항상 완벽한 솔루션"이 아닙니다. 그냥 말해
Code Roadie

2
@CodeRoadie 빠르고 더러운 것은 나를 위해 트릭을 만들었습니다. 실제 답변에 몇 가지 레이아웃 문제가있었습니다. "올바른 방법"으로 할 수 있지만 시간을 절약 해 주셔서 감사합니다!
Séraphin Hochart

@dGambit 참고 : "빠르고 더러운 "
Code Roadie

1
동적으로 뷰를로드 할 때 최근에 배운 UITextView것은 dlopen텍스트 입력을 지원하기 위해 호출 할 수 있다는 것 입니다. 이로 인해 UI 스레드가 크게 지연 될 수 있으므로이 방법이 훨씬 성능이 좋습니다!
야노

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

누군가를 돕는 희망!


14

github의 FXLabel은로 설정하여 즉시 사용할 label.contentModeUIViewContentModeTop있습니다. 이 구성 요소는 내가 만든 것이 아니지만 자주 사용하는 구성 요소이며 많은 기능이 있으며 제대로 작동하는 것 같습니다.


11

레이블 내부의 텍스트가 세로 중앙에 있지 않기 때문에이 글을 읽는 사람에게는 일부 글꼴 유형이 동일하게 설계되지 않았 음을 명심하십시오. 예를 들어, zapfino 크기가 16 인 레이블을 만들면 텍스트가 세로의 가운데에 완벽하게 배치되지 않은 것을 볼 수 있습니다.

그러나 helvetica로 작업하면 텍스트가 세로로 중앙에 배치됩니다.


많은 사용자 정의 글꼴이 세로 가운데 정렬되지 않습니다. UILabel 또는 UITextView는 항상 세로 가운데 정렬됩니다. iOS 프로그래밍에서 수직 정렬에 대해 생각할 필요가 없습니다.
Amit Singh

11

사용하십시오 textRect(forBounds:limitedToNumberOfLines:).

class TopAlignedLabel: UILabel {
    override func drawText(in rect: CGRect) {
        let textRect = super.textRect(forBounds: bounds, limitedToNumberOfLines: numberOfLines)
        super.drawText(in: textRect)
    }
}

당신은 신입니다!
Diogo Antunes

1
이 답변은 가야 방법 이 훨씬 좋은과 깨끗한 솔루션입니다으로 더 upvotes을!
Michael Ochs

10

UILabel을 서브 클래스하고 다음과 같이 그림 사각형을 구속합니다.

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

    [super drawTextInRect:rect];
}

줄 바꾸기 패딩과 관련된 솔루션을 시도하고 경우에 따라 잘못된 동작이 발생했습니다. 내 경험에 따르면 엉망보다 그림 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];
}

10

자동 레이아웃을 사용하는 경우 코드 또는 IB에서 세로 contentHuggingPriority를 ​​1000으로 설정하십시오. IB에서는 우선 순위를 1로 설정 한 다음 삭제하여 높이 구속 조건을 제거해야 할 수도 있습니다.


8

복잡한 작업을 수행하지 않는 한 UITextView대신 사용할 수 있습니다 UILabels.

스크롤을 비활성화하십시오.

텍스트가 완전히 사용자 sizeToFitsizeThatFits:메소드 만 표시되도록하려면


8

신속하게

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]. 감사합니다!
velkoon

7

이것은 오래된 솔루션입니다 .iOS에서 자동 레이아웃을 사용하십시오.

내 해결책 :

  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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.