개발/Swift

expandable + dynamic height tableview cell 구현하기

덤벨로퍼 2021. 9. 2. 18:24

데이터 값에 따라 유동적인 높이를 가진 Tableview를 구현 해야하고

그리고 해당 Tableview는 접기/펼치기 기능이 들어 있어야 할경우의 예시입니다.

우선 Tableview의 기본적인 구현 이 되어있다는 가정하에 진행합니다.

접기 펼치기 기능은 단순히 Row의(cell) 높이를 바꿔 주면 됩니다.

heightForRowAt 함수를 통해 유동적으로 cell의 높이를 지정 해주면 됩니다.


func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        print("heightForRowAt \(indexPath)")
        if helpViewModel.isSelectedCell(indexPath: indexPath) {
            return UITableView.automaticDimension
        }else {
            return 64
        }
    }

여기서 안펼친경우 64의 고정값을 줬으며

펼친경우 UITableView.automaticDimension 값을 주었습니다.

이렇게되면 isSelectedCell 값에 따라 유동적 으로 필요한 크기 만큼만 차지하게 됩니다.

다만 여기서 automaticDimension 을 사용하기 위해 중요한 부분은 cell의 제약조건이 명확히 주어져야 한다는것입니다. 그렇지 않은경우 올바른 높이 값이 나오지않아 저도 애를 먹었습니다.

automaticDimension 을 사용하여 만약 선택 되었다면 필요한 가장 큰 높이값을 가질것입니다.

선택되지 않았다면 64 값을 가지구요

이제 selectedCell 을 내부 값으로 저장해 사용하면 됩니다.

저장 값으로 indexPath를 사용했습니다. section 이 나뉘어져 있는경우 단순히 index로 구별이 힘들기 때문입니다.

 

var selectedCellIndex : [IndexPath] = []

func addToSelectedCellIndex(indexPath:IndexPath) {
        
        if isSelectedCell(indexPath: indexPath){
            if let index = selectedCellIndex.firstIndex(of: indexPath){
                selectedCellIndex.remove(at: index)
            }
        }else{
            selectedCellIndex.append(indexPath)

        }
        print(selectedCellIndex)
    }
    
    func isSelectedCell(indexPath:IndexPath) -> Bool{
        return selectedCellIndex.contains(indexPath)
    }

 

선택한 경우 selectedCellIndex 배열에 들어갑니다. 만약 이미 들어있다면 remove를 통해 제거합니다.

즉 toggle 이 더 맞는 표현입니다.

이제 마지막으로 viewController에서 didSelectRowAt 함수만 정의해 주면 됩니다.

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        helpViewModel.addToSelectedCellIndex(indexPath: indexPath)
        faqTableView.reloadRows(at: [indexPath], with: .automatic)
    }

 

위에서 구현한 addToSelectedCellIndex 함수를 사용하면 됩니다.

그리고 tableView를 reload 하여 테이블의 값을 갱신하면됩니다.

그러면 heightForRowAt 함수가 다시불려 높이값이 변경될 것입니다.