iOS : 자동 레이아웃의 여러 줄 UILabel


183

자동 레이아웃으로 매우 기본적인 레이아웃 동작을 달성하는 데 문제가 있습니다. 내 뷰 컨트롤러는 IB에서 다음과 같습니다.

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

맨 위 레이블은 제목 레이블이며, 몇 줄인지 알 수 없습니다. 모든 텍스트 줄을 표시하려면 제목 레이블이 필요합니다. 제목 바로 아래에 다른 두 개의 레이블과 작은 이미지를 배치해야하지만 키가 커야합니다. 레이블과 작은 이미지 사이의 세로 간격 제약 조건과 제목 레이블과 해당 슈퍼 뷰 사이의 상단 간격 제약 조건과 작은 이미지와 슈퍼 뷰 사이의 하단 간격 제약 조건을 설정했습니다. 흰색 UIView에는 높이 제한이 없으므로 하위 뷰를 포함하도록 세로로 늘려야합니다. 제목 레이블의 줄 수를 0으로 설정했습니다.

문자열에 필요한 줄 수에 맞게 제목 레이블의 크기를 조정하려면 어떻게해야합니까? 자동 레이아웃을 사용하고 있기 때문에 setFrame 메서드를 사용할 수 없다는 것을 이해하고 있습니다. 그리고 다른 레이아웃이 제목 레이블 아래에 있어야하기 때문에 자동 레이아웃을 사용해야합니다 (따라서 제약 조건).

어떻게하면 되나요?


3
나는 비슷한 문제로 싸우고 있습니다. 그러나 나는 여전히 최상위 레이블을 내용에 맞게 높이를 동적으로 조정하기 위해 고심하고 있습니다. 이것을 어떻게 달성 했습니까?
jbandi

1
@mwhuss의 답변을 허용 된 답변으로 표시하십시오.
jemmons

1
필요한 결과를 얻었습니까?
Aniruddha

이를 확인, 당신은 코드의 한 줄 추가해야 그나마 stackoverflow.com/a/36862795/4910767을
Badal 샤

답변:


254

사용 -setPreferredMaxLayoutWidth상의 UILabel나머지를 처리해야하고 자동 레이아웃.

[label setPreferredMaxLayoutWidth:200.0];

preferredMaxLayoutWidthUILabel 문서를 참조하십시오 .

최신 정보:

height스토리 보드 의 제약 조건 만으로 설정하면 Greater than or equal to되며 PreferredMaxLayoutWidth 를 설정할 필요가 없습니다.


8
어쨌든 인터페이스 빌더 에서이 작업을 수행합니까?
Sjoerd Perfors

12
또한 IB의 높이 제한을보다 크거나 같게 설정하십시오. "
jowie

10
알림 : numberOfLines 속성을 설정해야합니다.
리튬 Fumin

2
네, 원하는 최대 너비를 사용하십시오.
mwhuss

4
간단하지만 유익한 쓰기에 대해서는 devetc.org/code/2014/07/07/auto-layout-and-views-that-wrap.html 을 확인 하고 확인 하는 방법 은 stackoverflow.com/a/29180323/1529675 를 참조하십시오. 애니메이션 GIF (내 글이 아니라 Google을 통해 찾았습니다)preferredMaxLayoutWidth
tboyce12

213

라벨 세트 라인 수를 0으로 확장하고 자동 레이아웃 높이를> = x로 설정하는 것이 더 중요합니다. 자동 레이아웃이 나머지 작업을 수행합니다. 이전 요소를 기반으로 다른 요소를 포함하여 올바르게 배치 할 수도 있습니다.

자동 레이아웃


이 방법으로 문제가 해결되지 않으면 후속보기에서 자동 레이아웃이 여러 줄보기의 크기를 조정할 수 없도록하는 Cory Imdieke의 답변을 참조하십시오.
Tom Howard

1
이것은 테이블 뷰 셀 내에서 나를 위해 일한 유일한 대답입니다. 또한 고정 된 수의 행 (0 / 무제한 대신)으로 작동합니다.
bgolson

명시 적으로 선호하는 최대 너비를 설정하면 작동하지 않으므로이 기술을 사용할 때 IB에서 자동으로 설정되어 있는지 확인하십시오. 건배
jmc

자동 최대 너비 설정은 iOS8에서만 사용할 수 있습니다. 또한 내 이해에서 높이를 자동으로 조정하므로 내 경험에 따라 높이 제한을 설정할 필요가 없습니다. 이것은 명시 적 너비를 사용하여 나를 위해 일했습니다.
Tony

1
이것은 나를 위해 작동하지 않았습니다. stackoverflow.com/a/13032251/1529675 가 정답 이라고 생각 합니다.
tboyce12

48

출처 : http://www.objc.io/issue-3/advanced-auto-layout-toolbox.html

여러 줄 문자의 고유 내용 크기

UILabel 및 NSTextField의 내장 컨텐츠 크기는 여러 줄로 된 텍스트에는 모호합니다. 텍스트의 높이는 선의 너비에 따라 달라지며 구속 조건을 해결할 때 결정되지 않습니다. 이 문제를 해결하기 위해 두 클래스 모두 preferredMaxLayoutWidth라는 새로운 속성을 가지며, 이는 고유 컨텐츠 크기를 계산하기위한 최대 선 너비를 지정합니다.

우리는 일반적으로이 값을 미리 알지 못하므로이를 올바르게 달성하기 위해서는 2 단계 접근 방식이 필요합니다. 먼저 자동 레이아웃이 작동하게 한 다음 레이아웃 패스의 결과 프레임을 사용하여 원하는 최대 너비를 업데이트하고 레이아웃을 다시 트리거합니다.

- (void)layoutSubviews
{
    [super layoutSubviews];
    myLabel.preferredMaxLayoutWidth = myLabel.frame.size.width;
    [super layoutSubviews];
}

레이블이 프레임 세트를 가져 오려면 [super layoutSubviews]에 대한 첫 번째 호출이 필요하지만 변경 후 레이아웃을 업데이트하려면 두 번째 호출이 필요합니다. 두 번째 호출을 생략하면 NSInternalInconsistencyException 오류가 발생합니다. 제약 조건을 업데이트해야하는 레이아웃 패스를 변경했지만 레이아웃을 다시 트리거하지 않았기 때문입니다.

레이블 서브 클래스 자체에서도이를 수행 할 수 있습니다.

@implementation MyLabel
- (void)layoutSubviews
{
    self.preferredMaxLayoutWidth = self.frame.size.width;
    [super layoutSubviews];
}
@end

이 경우 layoutSubviews가 호출 될 때 레이블 자체에 이미 프레임이 있으므로 [super layoutSubviews]를 먼저 호출 할 필요가 없습니다.

뷰 컨트롤러 수준에서이 조정을 수행하기 위해 viewDidLayoutSubviews에 연결합니다. 이 시점에서 첫 번째 자동 레이아웃 패스의 프레임이 이미 설정되어 있으며이를 사용하여 원하는 최대 너비를 설정할 수 있습니다.

- (void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];
    myLabel.preferredMaxLayoutWidth = myLabel.frame.size.width;
    [self.view layoutIfNeeded];
}

마지막으로, 레이블의 내용 압축 저항 우선 순위보다 우선 순위가 높은 레이블에 명시 적 높이 제한이 없는지 확인하십시오. 그렇지 않으면 계산 된 내용의 높이보다 우선합니다. 라벨 높이에 영향을 줄 수있는 모든 구속 조건을 확인하십시오.


감사합니다. 코드뿐만 아니라 하위 클래스뿐만 아니라 뷰 컨트롤러에서도이를 수행하는 방법에 대한 설명과 예제에 대해 감사드립니다.
djibouti33

뷰 컨트롤러에서 이것을 시도하고 있는데 viewWillAppear 및 viewDidAppear 후에 viewDidLayoutSubviews가 호출됩니다. viewDidAppear 후 레이블 크기가 올바르게 조정되면 플래시가 발생합니다. 이것을 피할 수있는 방법이 있습니까? 사용자가 아무것도보기 전에 크기 조정을 완료하는 방법이 있습니까? 필자의 경우 여러 줄 레이블이 tableHeaderView에 있으므로이 예제를 사용하여 레이블을 기반으로 헤더보기의 높이를 조정하고 있습니다 ( stackoverflow.com/questions/20982558/… )
djibouti33

@ djibouti33 문제를 쉽게 확인할 수 있도록 최소 샘플 코드 (예 : github repo 형식)를 제공 할 수 있습니까?
Anton Matosov

@Anton에게 감사합니다. 우리의 디자인은 UITableView에서 UICollectionView로 전환되었으며, 다행히도이 동작을 보지 못했습니다. 작은 샘플 프로젝트를 만들기 위해 git history에 도달하면 알려 드리겠습니다.
djibouti33

iOS 9 sim에서 실행하기 시작한 이후 문제가되었지만 iOS 8에서 테스트하면 문제가 시작되었습니다. 최대 너비를 수동으로 설정해야합니다.
naz

17

나는이 정확한 시나리오와 싸우고 있었지만 필요에 따라 크기를 조정하고 축소하는 데 필요한 몇 가지 추가 견해를 가지고있었습니다. 그것은 나를 미치게 만들었지 만 마침내 알아 냈습니다.

핵심은 다음과 같습니다. Interface Builder는 뷰를 추가하고 이동할 때 추가 제약 조건을 적용하기를 좋아하지만 눈치 채지 못할 수도 있습니다. 내 경우에는 절반과 아래로 내려 가서 기본보기와 그 사이의 크기를 지정하는 추가 제약이 있습니다. 즉, 제약 조건에 위배되므로 그보다 더 큰 크기를 조정할 수 없습니다.

이런 경우인지 알 수있는 쉬운 방법은 레이블 크기를 수동으로 조정하는 것입니다. IB는 당신이 그것을 키울 수 있습니까? 그렇다면 아래 레이블이 예상대로 이동합니까? 구속 조건이 뷰를 어떻게 이동시키는 지 확인하기 위해 크기를 조정하기 전에이 두 가지를 모두 확인하십시오.

IB 메뉴

뷰가 멈춘 경우, 그 아래에있는 뷰를 따르고 그 중 하나에 제한을두기위한 상단 공간이 없는지 확인하십시오. 그런 다음 레이블의 줄 수 옵션이 0으로 설정되어 있는지 확인하고 나머지는 처리해야합니다.


그렇습니다. 많은 일을 한 후에 나는 원하는 효과를 얻을 수있었습니다. 원하는 제약 조건에 대해 매우 신중하게 생각해야합니다. IB가 예상치 못한 제약 조건을 끊임없이 던지는 데 도움이되지 않습니다.
James Harpe

5

다음이 필요하다는 것을 알았습니다.

  • 최고 제약
  • 선행 구속 조건 (예 : 왼쪽)
  • 후행 구속 조건 (예 : 오른쪽)
  • 콘텐츠 포옹 우선 순위를 가로로 낮게 설정하면 텍스트가 짧은 경우 지정된 공간을 채 웁니다.
  • 내용 압축 저항을 가로로 낮게 설정하면 더 넓어지지 않고 줄 바꿈됩니다.
  • 줄 수를 0으로 설정하십시오.
  • 줄 바꿈 모드를 자동 줄 바꿈으로 설정하십시오.

이것은 xcode9에서 작동합니다. 나는 레이블 높이 제한으로 아무것도 할 필요가 없었습니다 (아무것도 없습니다) : 레이블이 제한되면 (트레일 링, 선행, 상단 및 하단) 최근 상자에서 작동합니다. uikit는 나머지를 수행
Anton Tropashko

콘텐츠 포옹 우선 순위는 내 문제였습니다. 압축 저항뿐만 아니라 그 속성을 알게 해 주셔서 감사합니다. 한 시간 동안 문제를 해결하도록 도와주었습니다.
David Gay

0

주제에 대한 많은 주제에서 발견 된 다른 솔루션 중 어느 것도 내 경우에 완벽하게 작동하지 않았습니다 (동적 테이블 뷰 셀의 x 동적 멀티 라인 레이블).

나는 그것을 할 수있는 방법을 찾았다.

레이블에 제약 조건을 설정하고 여러 줄 속성을 0으로 설정 한 후 UILabel의 하위 클래스를 만듭니다. 내 AutoLayoutLabel이라고 전화했습니다.

@implementation AutoLayoutLabel

- (void)layoutSubviews{
    [self setNeedsUpdateConstraints];
    [super layoutSubviews];
    self.preferredMaxLayoutWidth = CGRectGetWidth(self.bounds);
}

@end

0

텍스트 줄 바꿈 레이블이있는 UITableViewCell이 있습니다. 다음과 같이 텍스트 줄 바꿈을 수행했습니다.

1) UILabel 제약 조건을 다음과 같이 설정하십시오.

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

2) 설정 번호 줄의 0.

3) UITableViewCell에 UILabel 높이 제한이 추가되었습니다.

@IBOutlet weak var priorityLabelWidth: NSLayoutConstraint!

4) UITableViewCell에서 :

priorityLabel.sizeToFit()
priorityLabelWidth.constant = priorityLabel.intrinsicContentSize().width+5

-12

한 가지 방법은 ... 텍스트 길이가 길어질수록 레이블 텍스트의 글꼴 크기를 변경 (감소)하려고합니다.

Label.adjustsFontSizeToFitWidth = YES;

1
뷰 컨트롤러의 다른 인스턴스가 일관된 모양을 갖기를 원하므로 글꼴 크기를 변경하고 싶지 않습니다.
James Harpe
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.