Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- uitableview
- Observable
- 스위프트
- swiftUI
- rxswift
- RxCocoa
- map
- Protocol
- clean architecture
- Human interface guide
- HIG
- MVVM
- 클린 코드
- tableView
- ribs
- 리펙터링
- 리팩토링
- ios
- Refactoring
- UICollectionView
- swift documentation
- Xcode
- SWIFT
- collectionview
- uiscrollview
- 애니메이션
- combine
- Clean Code
- UITextView
- 리펙토링
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - swift] extendable tableView 구현 방법 (동적으로 늘어나는 셀 구현), reloadRows(at:with:) 본문
UI 컴포넌트 (swift)
[iOS - swift] extendable tableView 구현 방법 (동적으로 늘어나는 셀 구현), reloadRows(at:with:)
jake-kim 2022. 12. 25. 22:50
Extendable tableVeiw 구현 아이디어
- 셀의 UI는 stackView에 label을 넣고 hidden을 on/off하며 펼쳐지거나 줄어들게끔 구현
- 데이터 소스 타입에 isDescHidden와 같이 플래그를 넣고, 확장하고 싶은 경우 isDescHidden을 false로 한 다음 해당 데이터 부분만 reloadRows(at:with:)을 통해 업데이트
- reloadRows(at:with:)에서 애니메이션도 지정할수 있는데, 아래로 팽창하듯이 늘어나는 옵션은 UITableView.RowAnimation.automatic 사용
// 해당 셀 업데이트
tableView.reloadRows(at: [IndexPath(row: indexPath.row, section: 0)], with: UITableView.RowAnimation.automatic)
구현 방법
- 셀에 표시될 데이터 소스 타입 정의
typealias Item = (title: String, desc: String, isDescHidden: Bool)
- 셀 정의
- hidden시키는 경우 intrinsic content size가 자동으로 줄어들어야 하므로, 편의를 위해 stackView를 사용
- descLabel을 hidden시킬 것
- 사용하는 쪽에서 prepare()를 호출하여 데이터 초기화
final class MyTableViewCell: UITableViewCell {
static let id = "MyTableViewCell"
private let stackView: UIStackView = {
let stackView = UIStackView()
stackView.axis = .vertical
stackView.translatesAutoresizingMaskIntoConstraints = false
return stackView
}()
private let titleLabel: UILabel = {
let label = UILabel()
label.font = .systemFont(ofSize: 24, weight: .bold)
label.numberOfLines = 1
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
private let descLabel: UILabel = {
let label = UILabel()
label.font = .systemFont(ofSize: 18, weight: .regular)
label.numberOfLines = 0
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
@available(*, unavailable)
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
contentView.addSubview(stackView)
[titleLabel, descLabel]
.forEach(stackView.addArrangedSubview(_:))
NSLayoutConstraint.activate([
stackView.leftAnchor.constraint(equalTo: contentView.leftAnchor),
stackView.rightAnchor.constraint(equalTo: contentView.rightAnchor),
stackView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor),
stackView.topAnchor.constraint(equalTo: contentView.topAnchor),
])
}
override func prepareForReuse() {
super.prepareForReuse()
self.prepare(item: nil)
}
func prepare(item: Item?) {
titleLabel.text = item?.title
descLabel.text = item?.desc
descLabel.isHidden = item?.isDescHidden ?? true
}
}
- tableView를 가지고 있는 ViewController 정의
class ViewController: UIViewController {
private let tableView: UITableView = {
let view = UITableView()
view.backgroundColor = .clear
view.separatorStyle = .none
view.bounces = true
view.showsVerticalScrollIndicator = true
view.contentInset = .zero
view.register(MyTableViewCell.self, forCellReuseIdentifier: MyTableViewCell.id)
view.estimatedRowHeight = 34
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
private var items = (0...50)
.map(String.init)
.map { val in
Item(title: val, desc: "long description, long description \n long descriptionlong descriptionlong descriptionlong description\n", isDescHidden: true)
}
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(tableView)
NSLayoutConstraint.activate([
tableView.leftAnchor.constraint(equalTo: view.leftAnchor),
tableView.rightAnchor.constraint(equalTo: view.rightAnchor),
tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
tableView.topAnchor.constraint(equalTo: view.topAnchor),
])
tableView.dataSource = self
tableView.delegate = self
}
}
- 데이터소스
extension ViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
items.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: MyTableViewCell.id, for: indexPath) as! MyTableViewCell
let item = items[indexPath.row]
cell.prepare(item: item)
return cell
}
}
- 셀을 탭했을 때, 데이터를 변경한 후 reload(at:with:) 호출
extension ViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let previous = items[indexPath.row]
items[indexPath.row] = Item(title: previous.title, desc: previous.desc, isDescHidden: false)
tableView.reloadRows(at: [IndexPath(row: indexPath.row, section: 0)], with: UITableView.RowAnimation.automatic)
}
}
* 전체 코드: https://github.com/JK0369/ExpendableTableView
* 참고
https://blog.devgenius.io/easy-way-to-create-an-expandable-uitableviewcell-in-swift-5-a5c72d1361da
'UI 컴포넌트 (swift)' 카테고리의 다른 글
[iOS - swift] 1. Sticky Header 구현 - 스크롤 시 상단 해더 숨기는 방법 (0) | 2023.01.07 |
---|---|
[iOS - swift] Custom Button 만드는 방법 (커스텀 버튼) (1) | 2023.01.04 |
[iOS - Swift] tableView, collectionView 스크롤 시 상단 뷰 흐리게 하는 방법 (네이버 웹툰 상단 뷰, Sticky Header) (0) | 2022.11.27 |
[iOS - Swift] TimerView 구현 방법 (썸네일 테두리 회전 뷰, progress, CAShapeLayer, UIBezierPath) (0) | 2022.09.08 |
[iOS - swift] Wave Animation (웨이브 애니메이션) (2) | 2022.06.30 |
Comments