본문 바로가기

Project/MovieClip

🤔 배우 프로필의 소개 부분 "더보기" "접기" 기능 구현

 

📌 배우 프로필에서 ‘더보기’ 기능 구현하기

UITableViewCell을 활용하여 배우의 소개글(biography)을 초기에 일정 줄까지만 보이도록 하고,
‘더보기’ 버튼을 눌러 전체 내용을 확장하는 기능을 구현하는 방법을 소개

 

🚀 1. 기능 개요

✅ 목표:

  1. 배우의 biography 내용을 UITableViewCell 내에서 일정 줄(5줄)까지만 표시
  2. 더보기 버튼을 누르면 전체 내용을 확장 (numberOfLines = 0)
  3. 접기 버튼을 누르면 다시 줄여서 (numberOfLines = 5) 표시
  4. UITableView의 셀 크기를 자동 조정하여 자연스럽게 확장/축소

 

✅ 2. PeopleOverviewTableViewCell 구현

배우의 biography를 표시하는 UITableViewCell을 만들고, 초기에 5줄까지만 보이도록 설정한 후, '더보기' 버튼을 추가

🔹 PeopleOverviewTableViewCell 코드

protocol PeopleOverviewTableViewCellDelegate: AnyObject {
    func didTapExpandButton(in cell: PeopleOverviewTableViewCell)
}

class PeopleOverviewTableViewCell: UITableViewCell {
    
    // MARK: - Variable
    static let reuseIdentifier: String = "PeopleOverviewTableViewCell"
    weak var delegate: PeopleOverviewTableViewCellDelegate?
    
    private var isExpanded: Bool = false   // ✅ 현재 셀의 확장 상태 저장
    
    
    // MARK: - UI Component
    private let overviewLabel: UILabel = {
        let label = UILabel()
        label.font = .systemFont(ofSize: 14, weight: .regular)
        label.numberOfLines = 5    // ✅ 기본적으로 5줄까지만 표시
        label.textColor = .white
        label.clipsToBounds = true // ✅ 초과 내용 숨김
        return label
    }()
    
    private let expandButton: UIButton = {
        let button = UIButton(type: .system)
        button.setTitle("더보기", for: .normal)
        button.setTitleColor(.systemBlue, for: .normal)
        button.backgroundColor = .black
        button.titleLabel?.font = .systemFont(ofSize: 14, weight: .bold)
        return button
    }()
    
    
    // MARK: - Init
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        contentView.backgroundColor = .black
        
        expandButton.addTarget(self, action: #selector(didTapExpandButton), for: .touchUpInside)
        
        configureConstraints()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    
    // MARK: - Function
    func configure(with content: String, isExpanded: Bool) {
        overviewLabel.text = content
        self.isExpanded = isExpanded
        
        overviewLabel.numberOfLines = isExpanded ? 0 : 5   // ✅ 확장 여부에 따라 줄 수 변경
        expandButton.setTitle(isExpanded ? "접기" : "더보기", for: .normal)
    }
    
    
    // MARK: - Action
    @objc private func didTapExpandButton() {
        delegate?.didTapExpandButton(in: self)
    }
    
    
    // MARK: - Layout
    private func configureConstraints() {
        contentView.addSubview(overviewLabel)
        contentView.addSubview(expandButton)
        
        overviewLabel.translatesAutoresizingMaskIntoConstraints = false
        expandButton.translatesAutoresizingMaskIntoConstraints = false
        
        NSLayoutConstraint.activate([
            
            overviewLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 15),
            overviewLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -15),
            overviewLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 10),
            overviewLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -10),
            
            expandButton.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -5),
            expandButton.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -15),
            expandButton.heightAnchor.constraint(equalToConstant: 20)
            
        ])
    }
}

 

✅ 3. PeopleDetatilViewController에서 확장 기능 추가

  • UITableView의 셀 확장 상태를 저장하는 expandedCells (Set<Int>) 추가
  • 더보기 버튼 클릭 시 Set<Int>에 해당 indexPath를 저장하여 확장 여부 관리
  • UIView.animate를 활용하여 부드럽게 업데이트

🔹 PeopleDetatilViewController 확장 기능 코드

class PeopleDetatilViewController: UIViewController {
    
    // ✅ 확장된 셀 저장
    private var expandedCells: Set<Int> = []
    
    // ... 생략
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        let sectionType = PeopleDetailSection.allCases[indexPath.section]
        
        switch sectionType {
            
        case .overview:
            
            guard let cell = tableView.dequeueReusableCell(withIdentifier: PeopleOverviewTableViewCell.reuseIdentifier, for: indexPath) as? PeopleOverviewTableViewCell else { return UITableViewCell() }
            
            guard let peopleDetail = peopleDetail else { return UITableViewCell() }
        
            let isExpanded = expandedCells.contains(indexPath.row)    // ✅ 확장 여부 확인
            
            if let biography = peopleDetail.biography, !(biography.isEmpty) {
                cell.configure(with: biography, isExpanded: isExpanded)
            } else {
                cell.configure(with: "정보 없음 😅", isExpanded: isExpanded)
            }
        
            cell.delegate = self
            
            return cell
            
        case .filmography:
            break
        }
        
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        cell.textLabel?.text = "Test"
        
        return cell
    }
}

// ✅ "더보기" 버튼 클릭 시 확장 상태 변경
extension PeopleDetatilViewController: PeopleOverviewTableViewCellDelegate {
    func didTapExpandButton(in cell: PeopleOverviewTableViewCell) {
        if let indexPath = peopleTableView.indexPath(for: cell) {
            
            if expandedCells.contains(indexPath.row) {
                expandedCells.remove(indexPath.row) // ✅ 이미 확장된 경우 제거
            } else {
                expandedCells.insert(indexPath.row) // ✅ 확장되지 않은 경우 추가
            }
            
            UIView.animate(withDuration: 0.3) {
                self.peopleTableView.reloadRows(at: [indexPath], with: .automatic)
            }
        }
    }
}

 

🎯 4. 최종 기능 동작 흐름

  1. overviewLabel은 기본적으로 5줄까지만 표시 (numberOfLines = 5)
  2. 더보기 버튼을 누르면 numberOfLines = 0이 되어 전체 텍스트 표시
  3. 접기 버튼을 누르면 다시 5줄까지만 표시
  4. UITableView의 reloadRows(at:with:)를 사용하여 해당 셀만 업데이트 (부드러운 애니메이션)
  5. expandedCells를 활용해 사용자가 스크롤해도 확장 상태 유지