Good afternoon,
I am trying to create expandable/ collapsible cells in a UICollectionViewController. The cells expand and collapse correctly. However, the information each cell holds stays present on the screen in the background. I will show pictures to explain. I am trying to delete the information from the view if the user collapses the cell, and insert it back if the user expands that cell.
The images below express the process of the cell starting in a collapsed state, expanding that cell, them collapsing that cell again. (note: this happens to every cell not just the first cell I clicked.
the first image is when the view loads and the cells are in the original collapsed state.
this second image shows when the user taps on the cell to expand it.
the third image shows when the user tries to collapse the cell.
the code that I use to expand and collapse the cells are below
fileprivate let cellId = "cellId"
fileprivate let headerId = "headerId"
fileprivate let profID = "profID"
private let headerIdentifier = "userProfileHeader"
private let sectionIdentifier = "sectionHeader"
var section:Int?
var expandSection = [Bool]()
var items = [String]()
fileprivate func setupCollectionView() {
collectionView.backgroundColor = .white
collectionView.contentInsetAdjustmentBehavior = .never
collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: cellId)
self.expandSection = [Bool](repeating: false, count: self.items.count)
collectionView.dataSource = self
collectionView.delegate = self
collectionView.register(userProfileHeader.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: headerIdentifier)
collectionView.register(sectionHeader.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: sectionIdentifier)
}
fileprivate func registerCollectionView() {
collectionView.register(profCell.self, forCellWithReuseIdentifier: "profCell")
self.collectionView.register(userProfileHeader.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: headerIdentifier)
self.collectionView.register(sectionHeader.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: sectionIdentifier)
}
var headerView: userProfileHeader?
var sectionView: sectionHeader?
override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
if kind == UICollectionView.elementKindSectionHeader {
let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: headerIdentifier, for: indexPath) as? userProfileHeader
if let user = self.user {
headerView?.myUser = user
} else if let userToLoad = self.userToLoad {
headerView?.myUser = userToLoad
}
return headerView!
} else {
let sectionViews = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: sectionIdentifier, for: indexPath) as? sectionHeader
let categories = ["Skills, Preferences", "Bio", "Reviews"]
sectionViews!.headerLabel.text = categories[indexPath.section]
sectionViews!.backgroundColor = .lightGray
return sectionViews!
}
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
return .init(width: view.frame.width, height: 340)
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return items.count
}
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
self.expandSection[indexPath.row] = !self.expandSection[indexPath.row]
self.collectionView.reloadItems(at: collectionView.indexPathsForSelectedItems!)
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "profCell", for: indexPath) as! profCell
if indexPath.row == 0 {
cell.educationView.text = user.education
cell.skillsView.text = user.skills
cell.preferencesView.text = "wassup bitches"
} else if indexPath.row == 1 {
cell.bioLabel.text = user.bio
} else if indexPath.row == 2 {
cell.labels.text = "Reviews"
}
}
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
if self.expandSection[indexPath.row] {
return CGSize(width: self.view.bounds.width - 20, height: 300)
}else{
return CGSize(width: self.view.bounds.width - 20, height: 80)
}
}
Instead of trying to insert and remove items inside
sizeForItemAt()
, callreloadSections(_ sections: IndexSet)
for the sections that get expanded or contracted. Then implementnumberOfItems(inSection section: Int)
to return 0 when contracted or items.count when expanded. Use sections to hold the top level items and cells to hold the collapsible sub-items.