와... 이틀간 삽질이 빛을 발했다...
오기가 생겨서 끝까지 붙잡고 있었더니 해결~!
뿌듯하니까 기록하도록한다.
음음... 내가 만들고 싶은 뷰는 말이지... CollectionView를 TableView에 넣고 싶단 말이다.
아 여기까지 들으면 쏘이지하지? 근데 조건은 CollectionView에 Cell이 몇개 들어있는지 몰라 ~ 랜덤하게 넣어줄거다.
자 그럼 '랜덤하게 넣어줄거다.'에서 벌써 Cell의 높이를 계산해서 보여줄수는 없게 된다.(몇개 들어있는지 모르니까!)
그렇담... 익히 들어왔던 UITableView.automaticDimension을 사용해야 한다.
(근데 이건 내가 써서 한번도 성공한 적이 없는거다. )
자. 제목에서도 썼다시피 Programmatically하게 할거다.
Storyboard, IB~이런거 다 안쓰고 오직 코드로만 하겠단 말이다.
1차시도도 기록했으면 좋으련만 ( 결과는 delegate를 안해서 실패였다.)!
class CollViewCell: UICollectionViewCell {
let theLabel = UILabel()
override init(frame: CGRect) {
super.init(frame: frame)
contentView.addSubview(theLabel)
theLabel.textColor = .black
theLabel.textAlignment = .center
contentView.backgroundColor = .clear
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemnted")
}
override func layoutSubviews() {
theLabel.translatesAutoresizingMaskIntoConstraints = false
theLabel.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
theLabel.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
theLabel.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
theLabel.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
}
}
^ CollectionView에는 Label밖에 안넣어줬기 때문에 설명은 생략한다.( 저런건 Anchor보다 UIEdgeInset을 쓰던데... 다음에 공부하더록하겠다.)
TableCell안에 CollectionView를 넣어줄거기 때문에 상속할것이.
UITableViewCell,
UICollectionViewDataSource,
UICollectionViewDelegate,
UICollectionViewDelegateFlowLayout 이렇게 있다.
code로 할거기 때문에 awakenib이 필요하는지는 잘 모르겠다.
있으니까 여기에도 init해준다.
class DynCollectionViewTableViewCell: UITableViewCell,
UICollectionViewDataSource,
UICollectionViewDelegate,
UICollectionViewDelegateFlowLayout {
//
var theCollectionView: UICollectionView!
var theCVHeight: NSLayoutConstraint!
var vContentSize: CGSize = CGSize.zero
var delegate : CollectionViewContentHeightDelegate?
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
self.contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight] //self.translatesAutoresizingMaskIntoConstraints = false
let layout = UICollectionViewFlowLayout.init()
layout.sectionInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
layout.scrollDirection = .vertical
theCollectionView = UICollectionView.init(frame: .zero, collectionViewLayout: layout)
theCollectionView.backgroundColor = .clear
contentView.addSubview(theCollectionView)
theCollectionView.delegate = self
theCollectionView.dataSource = self
commonInit()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
self.backgroundColor = .white
commonInit()
}
func commonInit() {
theCollectionView.translatesAutoresizingMaskIntoConstraints = false
theCollectionView.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor, constant: 16).isActive = true
theCollectionView.trailingAnchor.constraint(equalTo: self.contentView.trailingAnchor, constant: -16).isActive = true
theCollectionView.topAnchor.constraint(equalTo: self.contentView.topAnchor, constant: 1).isActive = true
theCollectionView.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor, constant: -1).isActive = true
//theCollectionView.heightAnchor.constraint(equalToConstant: 50).isActive = true
theCollectionView.register(CollViewCell.self, forCellWithReuseIdentifier: "cell")
theCVHeight = theCollectionView.heightAnchor.constraint(equalToConstant: 100)
theCVHeight!.priority = UILayoutPriority.init(999)
theCVHeight?.isActive = true
self.backgroundColor = .white
}
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
//랜덤 넘버 생성
let t = Int(arc4random_uniform(27)) + 3
return t
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CollViewCell
let c = UIColor.randomColor()
cell.backgroundColor = c
cell.theLabel.textColor = c.isDark ? .white : .yellow
cell.theLabel.text = "\(indexPath.row)"
if collectionView.contentSize != vContentSize {
self.vContentSize = collectionView.contentSize
self.theCVHeight?.constant = vContentSize.height
print("theContent Height \(theCVHeight?.constant)")
print("collectionView contentSize: \(collectionView.contentSize)")
}
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 100, height: 30)
}
}
여기의 로그를 확인해볼까?
collectionView contenSize : (Width , Height)이다. Height가 제각각인거 확인 했나?
자 이러고 나서 ViewController가서 신나게 AutomaticDimension이랑 estimated row 설정 했다.
결과는?
.
.
.
.
.
어림도 없지^^ 호락호락할거 같냐 이놈아!
계속 cell height가 일정하게 나오더랬다...(dynamic해야 하는데...)음음 뭐가 문젤까 하다가 Simulator를 건드리는 도중. 스크롤 할수록 ? Layout이 맞춰지는게 아닌가? 아 cell이 안보였다가 보여지게 되면 업데이트가 되는걸 어디서 봤더랬다. 그래서 그런가 하고? ScrollDid함수에다가 reload() 함수와 beginUpdate, endUpdate함수를 넣었더랬다.
결과는 ? 구현되는게 영 이상하다...
그러던 중 Update Layout을 찾아 봤고
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var cellHeight: CGFloat?
private var myTableView: UITableView!
//keeping track of the current open section
private var openSection: Int = 0
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.title = "Main View"
//get my sample data for loading the table view
//setup my table view
myTableView = UITableView()
myTableView.dataSource = self
myTableView.delegate = self
// myTableView.isDynamicSizeRequired = true
myTableView.register(DynCollectionViewTableViewCell.self, forCellReuseIdentifier: "cell")
myTableView.rowHeight = UITableView.automaticDimension
myTableView.estimatedRowHeight = 100
myTableView.translatesAutoresizingMaskIntoConstraints = false
myTableView.tableFooterView = UIView()
self.view.addSubview(myTableView)
myTableView.layer.borderWidth = 1
myTableView.layer.borderColor = #colorLiteral(red: 0.1921568662, green: 0.007843137719, blue: 0.09019608051, alpha: 1)
myTableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
myTableView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: -10).isActive = true
myTableView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
myTableView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
print("my tableView contentSize : \(myTableView.contentSize)")
}
override func viewDidLayoutSubviews() {
self.myTableView.beginUpdates()
self.myTableView.endUpdates()
}
//when user taps on the row
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("select")
}
//no of sections for the table view
func numberOfSections(in tableView: UITableView) -> Int {
return 10
}
//number of rows for that section
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
//render the cell and display data
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as? DynCollectionViewTableViewCell
print("this is VC :\(cell?.frame.height)")
return cell!
}
}
중에서 viewDidLayoutSubView()에서 업데이트 해줬더니 잘 돌아갔단 말이다.
이번 계기를 통해서 얻게된건... NSLayoutConstraint에 원하는 값을 넣을 수 있는것과 사용할 수 있게 된거다.
Priorty에 대해서는 내가 알고 쓴게 아니고 StackOverFlow뒤지다고 이렇게 바꾸래서 바꾼거다. 200했다 999했다 1000했다 많이 고쳤다. 흠 이만 ! 안녕 !