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

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

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

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



답변

에 수직 정렬을 설정하는 방법은 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;


답변

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

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

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

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

    [myLabel sizeToFit]

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

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


답변

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

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


답변

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

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

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


답변

무스, 소란 없음

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

}


답변

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


답변

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

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

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