-
확장 축소 가능한 동적 높이 TableView 구현 하기개발/Swift 2023. 4. 16. 13:46
Modern Collection View 와 MVVM 패턴 가이드
동적 높이 셀
동적 높이 테이블뷰
확장 축소 가능 테이블뷰
Table view높이 구하기
테이블뷰의 높이가 컨텐츠에따라 유동적으로 설정이 되려면 높이를 지정해주지 않고 제약조건을 잘 설정 해주면 된다.
titleLabel.snp.makeConstraints { make in make.top.equalTo(9) make.leading.equalToSuperview() make.trailing.equalTo(expandButton.snp_leading).offset(-8) } borderView.snp.makeConstraints { make in make.top.equalTo(titleLabel.snp_bottom).offset(9) make.height.equalTo(1) make.leading.trailing.equalToSuperview() } descLabel.snp.makeConstraints { make in make.top.equalTo(borderView.snp_bottom).offset(8) make.leading.trailing.bottom.equalToSuperview() }
Label 같은 경우는 높이가 컨텐츠에따라 유동적으로 변하므로
Top Bottom 에 관련한 제약조건을 잘 설정해 줘야하고
그렇지 않은 View는 높이를 지정해줘서 세로 제약조건이 모두 설정이 된다면
별다른 설정 없이도 Dynamic Height Cell을 구현 할수 있다.
Row Height , Estimate row height 이런거 안써도 됨
그리고 역시 TableView에 대한 제약조건도 역시 설정이 되어야한다.
TableView에 제약조건이 제대로 먹혀있지 않으면 테이블 셀 자체가 그려지지 않는다.
Expandable Cell 을 구현 하기 위해 Title Label , Desc Label 두개로 나누었으며
Collapse 된 상황에서는 Desc Label의 text를 빈값으로 바꾸고
Expand 상황에서는 text 를 올바르게 넣어줌으로써 확장 축소를 구현했다.
public func configure(title: String, desc: String, expand: Bool?) { titleLabel.text = title if let expand = expand, expand { setExpandedUI(desc: desc) } else { setCollapseUI() } } private func setCollapseUI() { titleLabel.numberOfLines = 1 expandButton.setImage(UIImage(named: "icDownArrow16"), for: .normal) descLabel.text = "" } private func setExpandedUI(desc: String) { titleLabel.numberOfLines = 2 expandButton.setImage(UIImage(named: "icUpArrow16"), for: .normal) descLabel.text = desc }
그러기 위해서 확장 축소 이벤트가 발생할 때마다
configure() 함수를 호출 시키고 expand 값을 전달 해줘야한다.
Observable.combineLatest(Observable.just(data), expandIndex.asObservable()) .map { list, expandIndex in var arr: [Data] = [] list.enumerated().forEach { arr.append(Data(title: $0.element.title, desc: $0.element.desc, expanded: $0.offset == expandIndex)) } return arr }.bind(to: expandableTableView.rx .items(cellIdentifier: ExpandableDialogTableViewCell.id)) {[weak self] index, data, cell in guard let cell = cell as? ExpandableDialogTableViewCell else { return } cell.configure(title: data.title, desc: data.desc, expand: data.expanded) cell.expandButton.rx.tap.bind { _ in self?.expandIndex.accept(index) }.disposed(by: cell.disposeBag) }.disposed(by: disposeBag)
Rx + TableView 를 사용해 구현헀다.
data 에는 전달할 컨텐츠 데이터가 들어있다.
expandIndex는 PublishRelay인데 int값을 전달한다.
확장 버튼을 누르면 해당 셀의 인덱스가 들어오고 그것에따라 expand 값을 넣어주었다.
TableView를 구현 하기 위해서 TableView 의 제약조건이나
Tableview의 부모 제약조건이 잘 설정 되어 있어야 한다.
그렇지 않으면 Cell이 하나도 그려지지 않는다.
위의경우 Tableview가 ContentView로 감싸져 있는 상황이었다.
ContentView 를 모달 처럼 투명 검정 배경에 띄우려는데
모달 안에 Table view 가있는 상황이다.
만약 여기서 더 나아가서
Cell 이아니라 Table View 자체의 높이가 유동적으로
변경되어야 한다면?
그러면 Content View이건 Table view이건 둘중 하나라도
고정 적인 높이가 지정되어 있어야 한다
contentView.snp.makeConstraints { make in make.leading.equalToSuperview().offset(16) make.trailing.equalToSuperview().offset(-16) make.centerY.equalToSuperview() } tableView.snp.makeConstraints { make in make.top.equalTo(closebutton.snp_bottom).offset(24) make.leading.equalTo(16) make.trailing.equalTo(-16) make.bottom.equalToSuperview().offset(-56) make.height.equalTo(500) }
나중에 Cell을 그리고 높이를 계산해서 높이를 다시 계산한다 한들
처음에 높이가 지정되어 있지 않으면
Cell 자체가 그려지지 않기 때문이다.
Cell의 높이를 구해서 유동적으로 Table view의 높이를 지정해줘야함 -> Cell 이 그려져야함 -> TableView 의 높이가 지정되야함 -> ?? 높이 모름
별짓 다해서 구현해본 결과 방법은 이것 뿐이었다.
결론은 Default 높이를 지정해준뒤 일단 table view를 그리고
높이를 다시 계산해서 다시 높이를 지정해주는것이다.
그래서 위처럼 테이블뷰 높이를 500으로 고정 시켜둔 것이다. 그렇게 해서 우선
table view의 셀들이 그려지게 한후
높이를 다시 받아서 사용하는 것이다.
높이를 받아오는 여러방법들 다 써봤는데 다 이상하게 나왔고
결국 Observe 를 쓰는게 제일 정확했다. (정확한 이름 까먹음)
tableView.rx.observe(CGSize.self, #keyPath(UITableView.contentSize)).bind { [weak self] size in guard let s = self, let height = size?.height else { return } s.tableView.snp.remakeConstraints { make in make.top.equalTo(s.closebutton.snp_bottom).offset(24) make.leading.equalTo(16) make.trailing.equalTo(-16) make.bottom.equalToSuperview().offset(-56) make.height.equalTo(height) } }.disposed(by: disposeBag)
이렇게 사이즈를 재조정 하면 됨!!
'개발 > Swift' 카테고리의 다른 글
Swift Bottom Sheet 바텀시트 구현하는 방법 + 동적 높이 할당 (0) 2023.05.24 Swift Tooltip 구현하는 방법 (2) 2023.05.21 Relay를 사용하면 무조건 메인스레드 일까 (0) 2023.04.02 Rxswift 네트워크 에러 핸들링 (0) 2023.04.02 Rx + TableView(CollectionView) 바인딩 안되는 오류 해결방법 (0) 2023.03.21