다음과 같은 화면을 섹션을 나눠서 TableView로 만들었는데 리뷰가 길거나 영화 제목?이 길면 그에따라 셀도 커졌으면 좋겠는데.. 하니까 바로 Dynamicheight를 설정할 수 있는걸 알고 사용한걸 정리해보았다.
Dynamic Height in TableView
tableView = UITableView(frame: view.bounds, style: .insetGrouped)
// dynamic height 설정
tableView.rowHeight = UITableView.automaticDimension
// 대략적인 높이를 설정해줘야함
tableView.estimatedRowHeight = 300
설정은 간단하다 추가로 대략적인 높이를 설정해줘야한다.
Cell 설정도 어렵지 않았다.
class MovieDescriptionCell: UITableViewCell {
lazy var titleLabel: UILabel = {
let label = UILabel()
label.font = .systemFont(ofSize: 24, weight: .black)
label.numberOfLines = 0
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
...
}
먼저 크기가 유동적일 수있는 Label에 대해서 보자.
내용이 길어져도 모두 표시할 수 있게 numberOfLines를 0으로 설정해줬다.
그리고 AutoLayout만 잘 설정해주면 된다.
// 라벨이 길어지면 밀리는거 때문에 priority 설정이 필요함
// 오류는 아니고 런타임중 경고? 보라색 경고떠서 추가함
// 실기기, 시뮬레이션에는 잘 나오지만 그래도 문제를 고쳐보려고 넣었다.
titleLabel.setContentHuggingPriority(.defaultHigh + 3, for: .vertical)
directorLabel.setContentHuggingPriority(.defaultHigh + 2, for: .vertical)
releaseDateLabel.setContentHuggingPriority(.defaultHigh + 1, for: .vertical)
//genreLabel.setContentHuggingPriority(.defaultHigh, for: .vertical)
// TableView의 DynamicHeight를 사용하려면 cell의 contentView에 넣고 constraint 정의해줘야함
// 이런 방식으로도 activate 가능
NSLayoutConstraint.activate([
posterView.topAnchor.constraint(equalTo: contentView.topAnchor),
posterView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
posterView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
posterView.heightAnchor.constraint(equalToConstant: 250),
titleLabel.topAnchor.constraint(equalTo: posterView.bottomAnchor, constant: 16),
titleLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 16),
titleLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -16),
directorLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 8),
directorLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 16),
directorLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -16),
releaseDateLabel.topAnchor.constraint(equalTo: directorLabel.bottomAnchor, constant: 8),
releaseDateLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 16),
releaseDateLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -16),
genreLabel.topAnchor.constraint(equalTo: releaseDateLabel.bottomAnchor, constant: 8),
genreLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 16),
genreLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -16),
// 마지막 요소의 bottomAnchor를 설정해야 동적 높이 계산 가능
genreLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -16)
])
주석에 좀 설명을 해뒀지만 여기서 중요한 포인트만 다시 글로 정리하지면,
1. 마지막 요소의 bottomAnchor를 설정해야 동적 높이 계산이 가능하다.
2. TableView Cell의 ContentView에 addsubView를 해주고 레이아웃을 정의해야 DynamicHeight가 감지하고 높이를 동적으로 변경한다.
3. 보라색 경고? 가 떠서 보니까 내가 설정한 레이아웃의 높이가 모호하다고 했다. 그래서 우선순위를 첫 라벨부터 하나씩 더 줘서 해결했다.
4. 이미지의 경우 이미지 크기를 그대로 Autolayout 설정때 사용하고 (임의로 어느정도 높이 맞춰주면 됌), 우선순위를 올려주면 된다. (위 코드에서는 이미지에 대한 내용 없음
collectionView 이미지 dynamic height ref
[iOS - swift] UICollectionView 동적인 셀 구현 방법 (Dynamic Cell Size, Dynamic height)
동적인 셀 UICollectionView나 UITableView를 사용할 때 동적인 셀 처리가 필요 Cell안에서 UIImageView에 URL을 가지고 image를 가져오는 피드와 같은 UI에 Cell의 height가 동적으로 변하는 경우가 존재 동적인 셀
ios-development.tistory.com
추가로 CollectionView에도 DynamicHeight를 할 수 있다.
private let collectionView = {
let layout = UICollectionViewFlowLayout()
let view = UICollectionView(frame: .zero, collectionViewLayout: layout)
view.register(MyCell.self, forCellWithReuseIdentifier: "cell")
// 이 부분
layout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
layout.minimumInteritemSpacing = 10
layout.minimumLineSpacing = 10
view.contentInsetAdjustmentBehavior = .always
return view
}()
FlowLayout을 사용할땐 위와같이 estimatedItemSize를 automaticSize로 변경해주면 되고,
만약 Compositional Layout을 사용한다면,,, LayoutSize 설정 옵션중에 .estimated를 사용해 대략적인 크기를 지정하고 유동적으로 사용할 수 있다.