UITableView 셀의 동적 높이 문제 (Swift)


79

가변 길이의 동적 텍스트가 tableview 셀 레이블에 삽입됩니다. tableview 셀의 높이를 동적으로 크기 조정하기 위해 다음을 구현했습니다 viewDidLoad().

self.tableView.estimatedRowHeight = 88.0
self.tableView.rowHeight = UITableViewAutomaticDimension

이것은 아직 스크롤되지 않은 UITableViewAutomaticDimention셀 (셀로 스크롤 할 때 호출 됨)에 대해 잘 작동 하지만 데이터가있는 테이블을로드 할 때 처음 화면에 렌더링되는 셀에는 적합하지 않습니다.

(다른 많은 리소스에서 제안한대로) 단순히 데이터를 다시로드 해 보았습니다.

self.tableView.reloadData()

viewDidAppear()그리고 둘 다 viewWillAppear()소용이 없었습니다. 나는 길을 잃었다 .. 누구든지 xcode가 화면에 처음로드 된 셀의 동적 높이를 렌더링하는 방법을 알고 있습니까?

더 나은 대체 방법이 있으면 알려주세요.


셀 설정에 대한 높이 제한이 올바르게 설정되어 있습니까? Xcode 6.3 버전을 사용하여 야생에서 이와 관련된 문제를 보지 못했습니다. 이 작업으로 github에 샘플 프로젝트가 있습니다. github.com/darren102/DTFAutomaticCellHeight
darren102

1
라벨의 잠재적 인 높이를 과도하게 보정하여이 문제를 해결했습니다. 아래 내 대답을 참조하십시오. 어쨌든 더 나은 솔루션이 있으면 알려주십시오!
단순성

답변:


115

이 시도:

func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

편집하다

func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

스위프트 4

func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

스위프트 4.2

func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableView.automaticDimension
}

두 방법 모두 위에 정의하십시오.
문제를 해결합니다.

PS :이 작업을 수행하려면 위쪽 및 아래쪽 제약 조건이 필요합니다.

여기에 예가 있습니다


3
@bashan 완벽하게 작동합니다. 적절한 제약 조건을 지정했는지 확인하십시오.
iDhaval

2
작동하지 않습니다. 단어가 너무 길지만 충분히 길지 않으면 버그가있는 것 같습니다. 제대로 렌더링되지 않습니다. 몇 마디이면 제대로 작동하는 것 같습니다.
Jeeves

6
하단 제약 조건을 추가하기 전까지는 작동하지 않았습니다. 이것이 작동하려면 상단 및 하단 제약 조건을 설정해야한다는 답변에 주목할 가치가 있다고 생각합니다.
Mitch Downey

2
이것이 작동하려면 하단 및 상단 구속이 필요합니다.
Antony Ouseph

2
은 "전지 요소"에 대한 하단과 상단 제약 작업이 필요합니다
EnasAZ

37

이것을 사용하십시오 :

tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 300

사용하지 마십시오 : heightForRowAtIndexPath델리게이트 함수

또한 스토리 보드에서 많은 양의 데이터가 포함 된 레이블의 높이를 설정하지 마십시오. top, bottom, leading, trailing제약을 주세요 .


4
하단 제약이 중요합니다! 나는 그것을 놓치고 높이를 계산할 수없는 이유가 궁금했습니다.
coyer

나는 이것을 남겨두고 있었다heightForRowAtIndexPath
500 서버 오류

@Javeed Static cell이나 Dynamic Cell 같은 곳 어디에서나 사용할 수 있다고 생각합니다.
ami rt

16

SWIFT 3

tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 160

과!!! StoryBoard에서 : 레이블에 대해 TOP 및 BOTTOM 제약 조건을 설정해야합니다. 다른 건 없습니다.


11

이 이상한 버그는 다른 답변으로 문제가 해결되지 않았기 때문에 Interface Builder 매개 변수를 통해 해결되었습니다.

내가 한 것은 기본 레이블 크기를 잠재적으로 콘텐츠가 될 수있는 것보다 크게 만들고 estimatedRowHeight높이에도 반영되도록하는 것뿐 이었습니다. 이전에는 Interface Builder에서 기본 행 높이를로 설정하고 88px컨트롤러에 반영했습니다 viewDidLoad().

self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 88.0

그러나 그것은 작동하지 않았습니다. 그래서 콘텐츠가 어쩌면 더 커지지 않을 것이라는 것을 깨달았 100px으므로 기본 셀 높이를 108px(잠재적 콘텐츠보다 큼)으로 설정하고 컨트롤러에 그렇게 반영했습니다 viewDidLoad().

self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 108.0

이것은 실제로 코드가 초기 레이블을 올바른 크기 로 축소 할 수있게했습니다 . 즉, 결코 더 큰 크기로 밖으로 확장 없지만, 항상 또한, 추가가 ... 아래로 축소 할 수 self.tableView.reloadData()필요하지 않았다 viewWillAppear().

나는 이것이 매우 가변적 인 콘텐츠 크기를 다루지 않는다는 것을 알고 있지만 콘텐츠가 가능한 최대 문자 수를 갖는 내 상황에서 작동했습니다.

이것이 Swift 또는 Interface Builder의 버그인지 확실하지 않지만 매력처럼 작동합니다. 시도 해봐!


나도 같은 문제가 있습니다. 내 대답을 업데이트했습니다. 그것은 내 문제를 해결했습니다. 이 방법 만 정의하고 높이와 관련된 모든 것을 제거하십시오.
iDhaval

8

행 높이 및 예상 행 높이에 대한 자동 치수를 설정하고 다음 단계를 확인하십시오.

@IBOutlet weak var table: UITableView!

override func viewDidLoad() {
    super.viewDidLoad()

    // Set automatic dimensions for row height
    // Swift 4.2 onwards
    table.rowHeight = UITableView.automaticDimension
    table.estimatedRowHeight = UITableView.automaticDimension


    // Swift 4.1 and below
    table.rowHeight = UITableViewAutomaticDimension
    table.estimatedRowHeight = UITableViewAutomaticDimension

}



// UITableViewAutomaticDimension calculates height of label contents/text
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    // Swift 4.2 onwards
    return UITableView.automaticDimension

    // Swift 4.1 and below
    return UITableViewAutomaticDimension
}

예를 들어 : UITableviewCell에 레이블이있는 경우

  • 줄 수 설정 = 0 (& 줄 바꿈 모드 = 꼬리 자르기)
  • 수퍼 뷰 / 셀 컨테이너에 대한 모든 제약 (위, 아래, 오른쪽 왼쪽)을 설정합니다.
  • 선택 사항 : 데이터가 없더라도 라벨로 덮는 최소 세로 영역을 원하는 경우 라벨의 최소 높이를 설정합니다.

다음은 동적 높이 제약이있는 샘플 라벨입니다.

여기에 이미지 설명 입력


1
Krunal이 언급 한 ViewDidLoad ()의 항목이 저에게 해결책이었습니다.
SHS

7

UITableView의 동적 크기 조정 셀에는 2 가지가 필요합니다.

  1. 테이블 뷰 셀 내에서 뷰의 올바른 제약 조건 설정 (대부분 뷰에 적절한 top, bottom 및 traling 제약 조건을 제공하는 것이 포함됨)
  2. viewDidLoad ()에서 TableView의 이러한 속성 호출

     tableView.rowHeight = UITableViewAutomaticDimension
    
     tableView.estimatedRowHeight = 140
    

이것은 swift 3로 작성된 자체 크기 조정 (동적 테이블 뷰 셀)에 대한 멋진 튜토리얼입니다.


6

Swift 3의 경우 다음을 사용할 수 있습니다.

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

3

Swift 4.2의 경우

@IBOutlet weak var tableVw: UITableView!

override func viewDidLoad() {
    super.viewDidLoad()

    // Set self as tableView delegate
    tableVw.delegate = self

    tableVw.rowHeight = UITableView.automaticDimension
    tableVw.estimatedRowHeight = UITableView.automaticDimension
}

// UITableViewDelegate Method 
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {

    return UITableView.automaticDimension
}

해피 코딩 :)


2

시험

override func viewWillAppear(animated: Bool) {
    self.tableView.layoutSubviews()
}

나는 같은 문제가 있었고 그것은 나를 위해 작동합니다.


나는 그것을 시도하고 무슨 일이 일어나는지 알려줄 것입니다. 제안 해 주셔서 감사합니다! 질문 한 지 거의 1 년이 지났지 만 제 답 외에는 다른 답을 찾지 못했습니다! 당신의 작품을 바랍니다!
simplexity

당신이 layoutsubviews 호출하기 전에 super.viewWillAppear은 (애니메이션)를 호출해야합니다
앨런 스카 르파

2

UITableViewCell의 자동 크기 조정이 작동하도록하려면 다음과 같이 변경해야합니다.

  • 스토리 보드에서 UITableView는 동적 프로토 타입 셀만 포함해야합니다 (정적 셀을 사용해서는 안 됨). 그렇지 않으면 자동 크기 조정이 작동하지 않습니다.
  • Storyboard에서 UITableViewCell의 UILabel은 위쪽, 아래쪽, 선행 및 후행 제약 조건 인 4 개의 제약 조건 모두에 대해 구성되었습니다.
  • Storyboard에서 UITableViewCell의 UILabel의 줄 수는 0이어야합니다.
  • UITableView Properties 아래에 설정된 UIViewController의 viewDidLoad 함수에서 :

    self.tableView.estimatedRowHeight = <minimum cell height> 
    self.tableView.rowHeight = UITableViewAutomaticDimension
    

정적 셀을 사용하여 동일하게 구현하는 방법은 무엇입니까?
Javeed dec

여기에 제공된 모든 솔루션을 시도한 후이 솔루션 ( <minimum cell height>for 설정)만이 estimatedRowHeight내 문제를 진정으로 해결했습니다. 그 전에는 셀 크기가 자동으로 조정되었지만 다양한 제약 경고가 표시되었습니다. 지금은 안돼! 그래서 감사합니다, 안슐 !!
RoberRM

2

Swift의 경우 iOS 9.0 및 iOS 11 에서도이 답변을 확인했습니다 (Xcode 9.3)

func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

여기에 위쪽, 아래쪽, 오른쪽 및 왼쪽 제약 조건 을 추가해야합니다.


2

제 경우에는-스토리 보드에서 아래 이미지와 같이 두 개의 레이블이 있었고 두 레이블 모두 동일한 너비 값을 설정하기 전에 원하는 너비 값을 설정했습니다. 선택을 취소하면 자동으로 변경되며 평소와 같이 아래 항목이 매력처럼 작동합니다.

1.rowHeight = UITableView.automaticDimension, and
2.estimatedRowHeight = 100(In my case).
3.make sure label number of lines is zero.

여기에 이미지 설명 입력


2

다른 사람들이 말한 것 외에도

수퍼 뷰와 관련된 레이블의 제약 조건을 설정하십시오!

따라서 레이블의 제약 조건을 주변의 다른 것들에 상대적으로 배치하는 대신 테이블 뷰 셀의 콘텐츠 뷰로 제한하십시오.

그런 다음 레이블의 높이가 0 이상으로 설정되고 줄 수는 0으로 설정되어 있는지 확인합니다.

그런 다음 ViewDidLoad추가 :

tableView.estimatedRowHeight = 695

tableView.rowHeight = UITableViewAutomaticDimension

SUPERVIEW와 관련된 레이블의 제약 조건을 설정하십시오! : 내 시간을 절약했습니다! 감사합니다.
ACAkgul

2

다음 두 가지 작업을 수행하면 간단합니다.

  1. 자동 높이 설정
tableView.rowHeight = UITableView.automaticDimension
  1. 위에서 아래 로 FULL 제약 조건을 사용하여 모든 TableViewCell을 생성합니다 . 마지막 요소 는 셀을 끝내기 위해 일부 하단 간격을 정의 해야 합니다.

따라서 레이아웃 엔진은 셀 높이를 계산하고 값을 올바르게 적용 할 수 있습니다.


1

나는 당신의 솔루션에 영감을 받아 다른 방법을 시도했습니다.

추가 해보세요 tableView.reloadData()viewDidAppear() .

이것은 나를 위해 작동합니다.

스크롤링 뒤에있는 것은 reloadData와 "동일"하다고 생각합니다. 화면을 스크롤 reloadData()하면viewDidAppear .

이것이 효과가 있다면 plz는이 답변에 답장 하여이 솔루션을 확신 할 수 있습니다.


동일한 솔루션을 생성하는지 확인하기 위해 시도하고 업데이트하겠습니다. 감사!
simplexity

죄송 합니다만 이상하게도 레이아웃에 영향을주지 않았습니다. 적절한 크기로 줄이지 않고 Interface Builder에서 설정 한 정적 값으로 남겨 두었습니다.
simplexity

1

불행히도 내가 무엇을 놓쳤는 지 잘 모르겠습니다. 위의 방법은 xib 셀의 높이를 얻거나 layoutifneeded () 또는 UITableView.automaticDimension이 높이 계산을 수행하도록 허용하지 않습니다. 나는 3 ~ 4 박 동안 검색하고 노력했지만 답을 찾을 수 없었다. 여기 또는 다른 게시물에 대한 일부 답변은 해결 방법에 대한 힌트를 제공했습니다. 어리석은 방법이지만 작동합니다. 모든 셀을 배열에 추가하기 만하면됩니다. 그런 다음 xib 스토리 보드에서 각 높이 제한의 콘센트를 설정합니다. 마지막으로 heightForRowAt 메서드에 추가합니다. 해당 API에 익숙하지 않은 경우 간단합니다.

스위프트 4.2

CustomCell.Swift

@IBOutlet weak var textViewOneHeight: NSLayoutConstraint!
@IBOutlet weak var textViewTwoHeight: NSLayoutConstraint!
@IBOutlet weak var textViewThreeHeight: NSLayoutConstraint!

@IBOutlet weak var textViewFourHeight: NSLayoutConstraint!
@IBOutlet weak var textViewFiveHeight: NSLayoutConstraint!

MyTableViewVC.Swift

.
.
var myCustomCells:[CustomCell] = []
.
.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = Bundle.main.loadNibNamed("CustomCell", owner: self, options: nil)?.first as! CustomCell

.
.
myCustomCells.append(cell)
return cell

}


override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {

   let totalHeight = myCustomCells[indexPath.row].textViewOneHeight.constant + myCustomCells[indexPath.row].textViewTwoHeight.constant +  myCustomCells[indexPath.row].textViewThreeHeight.constant + myCustomCells[indexPath.row].textViewFourHeight.constant + myCustomCells[indexPath.row].textViewFiveHeight.constant

  return totalHeight + 40 //some magic number


}

1

나는 이것을 사용한다

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {

    return 100
}

0

셀 뷰 / 뷰의 각 객체에 대해 TOP , BOTTOMHEIGHT에 대한 모든 제약 조건을 설정하고있는 경우 중간 Y 위치에 존재하는 것을 제거 해야합니다. 당신이 이것을하지 않은 곳에서 다른 뷰에 아티팩트를 넣습니다.


3
안녕하세요!,이 답변은 좋을 수 있지만 답변을 설명하고 보여주는 실제 예제를 제공하는 것이 좋습니다.
ItamarG3 2017-06-26

0

객관적인 c의 경우 이것은 내 좋은 솔루션 중 하나입니다. 그것은 나를 위해 일했습니다.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    cell.textLabel.text = [_nameArray objectAtIndex:indexPath.row];
    cell.textLabel.numberOfLines = 0;
    cell.textLabel.lineBreakMode = NSLineBreakByWordWrapping;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return UITableViewAutomaticDimension;
}

이 두 가지 변경 사항을 적용해야합니다.

1)cell.textLabel.numberOfLines = 0;
  cell.textLabel.lineBreakMode = NSLineBreakByWordWrapping;

2)return UITableViewAutomaticDimension;

0

나는 또한 처음 에이 문제가 발생 했으며이 코드에서 내 문제를 해결했습니다.이 코드 self.tableView.reloadData()대신 동적 높이를 사용하지 마십시오.

[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade];

0

정적을 사용할 때 s의 UITableView모든 값을 설정 UILabel한 다음을 호출 tableView.reloadData()합니다.


0
self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 88.0

그리고 레이블에 대한 botton 제약 을 추가하는 것을 잊지 마십시오


0

스위프트 5 엔조이

tablev.rowHeight = 100
tablev.estimatedRowHeight = UITableView.automaticDimension


func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = self.tablev.dequeueReusableCell(withIdentifier: "ConferenceRoomsCell") as! ConferenceRoomsCell
    cell.lblRoomName.numberOfLines = 0
    cell.lblRoomName.lineBreakMode = .byWordWrapping
    cell.lblRoomName.text = arrNameOfRooms[indexPath.row]
    cell.lblRoomName.sizeToFit()
    return cell
}

-1
self.Itemtableview.estimatedRowHeight = 0;
self.Itemtableview.estimatedSectionHeaderHeight = 0;
self.Itemtableview.estimatedSectionFooterHeight = 0;


[ self.Itemtableview reloadData];
self.Itemtableview.frame = CGRectMake( self.Itemtableview.frame.origin.x,  self.Itemtableview.frame.origin.y,  self.Itemtableview.frame.size.width,self.Itemtableview.contentSize.height + self.Itemtableview.contentInset.bottom + self.Itemtableview.contentInset.top);

이 코드가 문제를 해결할 수 있지만 문제를 해결하는 방법과 이유에 대한 설명포함 하여 게시물의 품질을 향상시키는 데 실제로 도움이되며 아마도 더 많은 찬성 투표를 받게됩니다. 지금 질문하는 사람뿐만 아니라 미래에 독자를 위해 질문에 답하고 있다는 것을 기억하십시오. 제발 편집 설명을 추가하고 제한 및 가정이 적용 무엇의 표시를 제공하는 답변을.
Suraj Rao

-3

적절한 제약 조건을 설정하고 위임 메서드를 다음과 같이 업데이트합니다.

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

이렇게하면 동적 셀 높이 문제가 해결됩니다. 그렇지 않은 경우 제약 조건을 확인해야합니다.


1
이 같은 페이지에서 Ahmed Lotfy의 답변 과 동일한 코드 ...
Eric Aya

흠, 나는 신속한 3. *를 확인했습니다. Ahmed ans를 놓쳤습니다
Kanjariya-IOS

1
당신은 일에 코드뿐만 아니라 추정 행 높이를 제공해야
모흐센 Shakiba
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.