자체 크기 조정 UITableViewCell 내부의 여러 UILabel
iOS 8 앱에는 뷰가 있고 자체 크기 조정이 필요합니다. 자동 레이아웃을 사용하여 구현 작동합니다. 거의. 이제 어떻게 생겼는지 보여 드리겠습니다.
셀 안에 3 개의 레이블이 있습니다. lorem ipsum 텍스트가있는 기본 레이블입니다. 숫자 숫자가있는 부제 (두 개의 개의 개의 인화입니다. 색상이 같기 때문에 혼란 스러울 수 있습니다.) 그런 다음 작은 검은 색 텍스트가있는 세 번째 레이블입니다.
첫 번째 레이블은 문제없이 선택 크기가 조정됩니다. 그러나 문제는 세 번째 작은 레이블에 있습니다. 보시다시피 모든 텍스트에 맞게 크기가 조정되지 않습니다.
이제 이상한 일이 일어나고 있습니다. 나는 그것을 풍경화하고 여기 있습니다.
공간이 있기 때문에 레이블은 예상되는 전체 텍스트를 표시합니다. 좋아. 그런 다음 다시 초상화로 되돌립니다.
이제 작은 레이블이 모든 텍스트에 맞게 크기가 조정 모든 셀 경계를 넘었습니다. 셀을 더 크게 만들려고했습니다. 이것은 자체 크기 조정 셀이기 때문에 올바른 방법이라고 생각하지 않습니다.
자동 레이아웃 제약에 대한 오류나 경고도받지.
이 두 줄의 코드를 viewDidLoad()
메서드에 설정했습니다.
tableView.estimatedRowHeight = 100
tableView.rowHeight = UITableViewAutomaticDimension
아무도 내가 여기서 뭘 잘못하고 있는지 말해 줄 수 있습니까?
이미지 만보 고 대답하기 어렵고 위의 스 니펫 옆에 게시 할 코드가 더 이상 없기 때문에 여기 에 문제를 해결 실행 가능한 Xcode 프로젝트를 업로드했습니다 . (2 개의 사용자 지정 셀이 있습니다. 기본적으로 동일한 셀은 두 번째 셀에서 높이 만 증가합니다.)
나는 자동 레이아웃 제약을 다루고 있었지만 작동하지 않는 것입니다. 어떤 도움을 주시면 감사하겠습니다.
감사합니다.
최신 정보 :
이 튜토리얼 의 도움으로 몇 가지 유용한 정보를 찾았습니다. 모든 따르면, 각 서브 뷰는 고정하는 조건이 있고 자동 레이아웃이 셀의 높이를 계산하는 데 도움이되는 제약 조건이 아래로 이동해야합니다. 내 원래 게시물에서는 각 레이블 사이에 세로 공간이있어서 자동 레이아웃이 적절한 높이를 계산할 수없는 이유라고 생각합니다.
그래서 몇 가지 변경했습니다.
- 레이블 사이의 수직 공간을 0으로 전면 상단 및 중간 레이블과 중간 및 하단 레이블 사이의 수직 공간 제약 조건을 설정했습니다.
- 맨 위 레이블에 선행, 맨 위, 후행 제약 조건을 추가했습니다.
- 중간 레이블의 선행 및 후행.
- 선행, 하단, 하단 레이블의 후행.
이제 또 다른 이상한 부분이 있습니다. 처음부터 끝까지 레이블 자르기 문제가 여전히 존재합니다.
그러나 장치를 가로로 회전하고 다시 세로로 돌리면 모든 셀의 크기가 두 레이블에 맞게 조정됩니다!
그래도 왜 이것이 처음에는 일어나지 않는지 알 수 없습니다. 업데이트 된 Xcode 프로젝트가 여기 있습니다 .
여기서 문제는 여러 줄 레이블의 preferredMaxLayoutWidth
속성에 있습니다. 이 단어 줄 바꿈이 필요한시기를 알려주는 속성입니다. 각 레이블 intrinsicContentSize
이 올바른 높이를 가지려면 그래도 설정해야합니다 . 이는 즉, 즉 자동 레이아웃이 셀의 높이를 결정하는 데 사용하는 것입니다.
Xcode 6 Interface Builder는이 속성을 자동으로 설정하는 새로운 옵션을 도입했습니다 . 안타깝게도 펜촉이나 스토리 보드에서 셀을로드 할 때 버그 / 자동으로 설정되지 않는 심각한 버그 (Xcode 6.2 / iOS 8.2 기준)가 있습니다.
이 버그를 해결 preferredMaxLayoutWidth
하고 레이블이 테이블에 표시되면 최종보기와 정확히 일치 하도록 설정해야합니다. 실제로 셀을 수행하기 전에 다음을 수행해야합니다 tableView:cellForRowAtIndexPath:
.
cell.nameLabel.preferredMaxLayoutWidth = CGRectGetWidth(cell.nameLabel.frame)
cell.idLabel.preferredMaxLayoutWidth = CGRectGetWidth(cell.idLabel.frame)
cell.actionsLabel.preferredMaxLayoutWidth = CGRectGetWidth(cell.actionsLabel.frame)
이 코드 만 추가해도 작동하지 않는 이유는 3 줄의 코드가 실행될 tableView:cellForRowAtIndexPath:
때 각 레이블의 너비를 사용하여 설정하기 때문입니다. preferredMaxLayoutWidth
그러나이 시점에서 레이블의 너비를 확인하면 시간이 지남에 따라 레이블 너비는 셀이 표시되고 하위 뷰가 배치 될 때까지 완전히 완전히 완전히 삭제됩니다.
이 시점에서 정확한 라벨 너비를 최종 너비를 반영하는 방법은 무엇입니까? 모든 것을 하나로 묶는 코드는 다음과 가능합니다.
// Inside of tableView:cellForRowAtIndexPath:, after dequeueing the cell
cell.bounds = CGRect(x: 0, y: 0, width: CGRectGetWidth(tableView.bounds), height: 99999)
cell.contentView.bounds = cell.bounds
cell.layoutIfNeeded()
cell.nameLabel.preferredMaxLayoutWidth = CGRectGetWidth(cell.nameLabel.frame)
cell.idLabel.preferredMaxLayoutWidth = CGRectGetWidth(cell.idLabel.frame)
cell.actionsLabel.preferredMaxLayoutWidth = CGRectGetWidth(cell.actionsLabel.frame)
좋아, 우리 여기서 뭐하는거야? 3 줄의 새로운 코드가 추가 할 수 있습니다. 먼저, 테이블 뷰의 실제 너비와 일치하는 것이 테이블 뷰 셀의 너비를 설정해야합니다 (이는 테이블 뷰가 이미 레이아웃 가정합니다). 테이블 뷰가 결국 할 것이기 때문에 우리는 예약 셀 너비를 수정하고 있습니다.
또한 우리가 99999
높이로 사용 하고 있음을 알 수 있습니다 . 그게 뭔데? 이것은 여기 에서 자세히 논의 된 문제에 대한 간단한 해결 방법입니다. 제약 조건에 셀의 contentView의 현재 높이보다 더 많은 수직 공간이 필요한 경우 실제로 실제 문제를 해결하지 않고 예외가 발생합니다. 각 레이블에 대한 최종 너비를 가져 오는 데에만 관심이 있기 때문에 셀 또는 하위 뷰의 높이는 시점에서 중요하지 않습니다.
다음으로, contentView의 경계를 셀의 경계와 동일하게 설정하여 셀의 contentView가 방금 셀 자체에 할당 한 크기와 동일한 지 확인합니다. 생성 한 모든 자동 레이아웃 제약이 필요합니다. contentView가 해결 되려면 올바른 크기가 있습니다. 셀의 크기를 수동으로 설정하는 것만으로는 있는 contentView 크기가 일치 여부의하도록 자동 으로 조정되지 않습니다 .
마지막으로, 자동 레이아웃 엔진이 제약 조건을 해결하고 모든 하위 뷰의 프레임을 업데이트하도록 셀에 레이아웃 패스를 강제합니다. 이제 셀 및 contentView의 너비가 테이블보기에서 가동시와 동일하고 레이블도 있습니다. 즉, 각 preferredMaxLayoutWidth
레이블에 대한 세트가 말하는 레이블이 적절한 시간에 래핑합니다. 여기서는 셀이 테이블보기에서 물론 때 레이블의 높이가 설정을 의미합니다!
이것은 분명히 UIKit의 애플 버그로, 해결해야 우리 당분간 합니다 ( 애플에 버그 보고서 를 제출 하여 우선 순위를 정할 수 있도록하십시오!).
마지막 참고 : 해결 방법은이 테이블 뷰-cell의 contentView
너비가 테이블 뷰 의 전체 너비를 확장하지 않는 경우 (예 : 오른쪽에 섹션 인덱스가 표시되는 경우) 문제가됩니다. 이 경우 셀에서 접근 할 때이를 수동으로합니다. 다음과 같이 하드 코딩해야 할 수도 있습니다.
let cellWidth = CGRectGetWidth(tableView.bounds) - kTableViewSectionIndexWidth
cell.bounds = CGRect(x: 0, y: 0, width: cellWidth, height: 99999)
나는 당신과 같은 문제를 만났고 해결 해결을 찾았습니다.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// dequeue cell...
// do autolayout staffs...or if the autolayout rule has been set in xib, do nothing
[cell layoutIfNeeded];
return cell;
}
그리고 자체 크기 조정이 잘 작동했습니다. 내 코드에서 두 개의 레이블을 세로로 배치 둘 다 동적 높이입니다. 두 개의 레이블을 포함하도록 셀 높이가 설정되었습니다.
다른 사람들이 제안한 것처럼 제약 조건에 여러 가지 오류가있는 가정하면이 문제는 UITableViewCellAccessory를 사용하여 발생하는 것과 함께 제안합니다. iOS가 셀을 배치하고 높이를 배치 할 때 액세서리로 인해 발생하는 폭의 작업 변경을 고려하지 않고 예상치 못한 부분이 잘립니다.
UILabel이 콘텐츠 뷰의 전체 너비를 확장하기를 원한다고 가정하고 모든 글꼴 크기에 대해 수정하는 방법을 작성했습니다.
-(void)fixWidth:(UILabel *)label forCell:(UITableViewCell *)cell {
float offset = 0;
switch ([cell accessoryType]) {
case UITableViewCellAccessoryCheckmark:
offset = 39.0;
break;
case UITableViewCellAccessoryDetailButton:
offset = 47.0;
break;
case UITableViewCellAccessoryDetailDisclosureButton:
offset = 67.0;
break;
case UITableViewCellAccessoryDisclosureIndicator:
offset = 33.0;
break;
case UITableViewCellAccessoryNone:
offset = 0;
break;
}
[label setPreferredMaxLayoutWidth:CGRectGetWidth([[self tableView]frame]) - offset - 8];
}
cellForRowAtIndexPath에 추천하십시오.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
#Setup the cell
...
// Fix layout with accessory view
[self fixWidth:[cell label] forCell:cell];
return cell;
}
너비를 확실하게 조정 한 다음 적절한 높이를 다시 계산하기 위해 여러 줄이있는 레이블에 대해 작업을 수행합니다. 동적 글꼴 크기 작동합니다.
smileyborg가 언급했듯이 contentView의 전체 너비를 사용하지 않는 경우 제약 조건을 참조하고 너비에서도 뺄 수 있습니다.
편집 : 이전에 셀에서 'layoutIfNeeded'를 실행했지만 성능 문제가 발생했으며 어쨌든 필요하지 않은 것 같습니다. 그것을 제거해도 문제가 발생하지 않았습니다.
여기에 두 가지 문제가 있습니다.
1 / 현재 Visual Format Language를 사용하여 셀의 수직 제약 조건을 다음과 같이 번역 할 수 있습니다.
Cell: "V:|-(10)-[nameLabel]-(67)-|"
그런 다음 두 번째 제약 조건 그룹을 설정합니다.
Cell: "V:|-(10)-[nameLabel]-(8)-[pnrLabel]-(2)-[actionsLabel]"
이 두 그룹의 제약 조건은 잘 섞일 수 없으며 두 번째 문제와의 모호성을 드러냅니다.
2 / 어떤 이유로 actionsLabel
앱을 시작할 때 한 줄로 제한됩니다. 그런 다음 장치를 가로 모드로 회전하면 actionsLabel
두 줄 이상으로 표시되도록 수락합니다. 그런 다음 기기를 다시 세로 모드로 돌리면에서 actionsLabel
두 줄 이상을 계속 표시합니다. 그러나 actionsLabel
실제로 셀 높이 제한의 일부가 아니기 때문에 셀 경계와 겹칩니다.
이러한 모든 문제를 해결하려면 먼저 xib 파일을 처음부터 다시 빌드하는 것이 좋습니다. 이렇게하면 actionsLabel
이상한 동작 이 치료됩니다 (장치를 회전 할 때만 두 줄 이상).
그런 다음 다음과 같이 제약 조건을 정의해야합니다.
Cell: "V:|-(10)-[nameLabel(>=21)]-(8)-[pnrLabel(>=21)]-(2)-[actionsLabel(>=21)]-(10)-|"
물론 레이블에 대한 다른 최소 높이 제약 조건을 정의 할 수 있습니다 (>=21)
. 같은 방식으로 하단 여백을 -(10)-
.
추가
귀하의 질문에 답하기 위해 .xib 파일에 이전 제약 조건 패턴을 사용하여 간단한 프로젝트를 만들었습니다. 다음 이미지는 자신의 제약 조건을 구축하는 데 도움이 될 수 있습니다.
나는 "fogisland"의 매우 쉽고 우아하게 보이는 솔루션을 시도했지만 작동하지 않았습니다. 운 좋게도 하나의 추가 라인이 모든 방향에서 작동한다는 것을 알았습니다. 시스템에 새 레이아웃 (layoutIfNeeded)을 제안 할뿐만 아니라 명시 적으로 요청 (setNeedLayout)한다고 알려주세요.
cell.setNeedsLayout()
cell.layoutIfNeeded()
return cell
참고 URL : https://stackoverflow.com/questions/25947146/multiple-uilabels-inside-a-self-sizing-uitableviewcell
'ProgramingTip' 카테고리의 다른 글
정의되지 않은 동작 밖에서 전역 배열에 액세스하고 동작합니까? (0) | 2020.12.04 |
---|---|
Android Studio 키보드 단축키 제어 (0) | 2020.12.03 |
Java ArrayList의 시간 짜고 (0) | 2020.12.03 |
SQL Server의 모든 데이터베이스에있는 모든 테이블의 열 이름을 찾는 방법 (0) | 2020.12.03 |
버그 오류 : werkzeug.routing.BuildError (0) | 2020.12.03 |