I am making an expandable UICollectionViewCell
as below.
Currently, I have registered a
UICollectionViewCell
named ExpandableCell
in CollectionView
In order to express the horizontal scroll section and arrow cell within this
ExpandableCell
, a CollectionView is constructed using DiffableDataSource and CompositionalLayout.
(I know I don't have to create a CollectionView again in the cell if I am in a best case, but I had to work like this because of the current project environment.)
When clicking on a cell with an arrow, the event is delivered to the
ViewController
using the delegate pattern, where the ViewController's instance property called isExpand
is changed and the self.collectionView.reloadItems(at: expandableCellIndexPath)
is called.
extension ViewController: ExpandableCellDelegate {
func expandableCell(_ cell: ExpandableCell, didSelectExpand isExpand: Bool) {
self.isExpand = isExpand
let expandableCellIndexPath = [IndexPath(row: 0, section: 0)]
self.collectionView.reloadItems(at: expandableCellIndexPath)
}
}
Then, the size is recalcualted in
sizeForItemAt
, and ExpandableCell
recreates and sets a snapshot that fits the expand state through cell.configure (isExpand: isExpand)
in cellForItemAt
as below.
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ExpandableCell",
for: indexPath) as! ExpandableCell
cell.delegate = self
cell.configure(isExpand: self.isExpand)
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: view.window?.bounds.width ?? .zero,
height: self.isExpand ? 101 : 61)
}
Looking at the situation up to here in gif, it works the way I wanted it to.
The problem is that after scrolling horizontally in the section of each item and expanding cell, the previously scrolled position in the section is not maintained.
When the cell is folded back, it returns to the position it was scrolled in folded state.
When cell is expanded, expanded cell also also has its own scroll position, so the positions are displayed differently when I expand and fold the cell.
If I configure the cell and invoke invalidLayout inside the delegate function as shown below, it works the way I want it to.
extension ViewController: ExpandableCellDelegate {
func expandableCell(_ cell: ExpandableCell, didSelectExpand isExpand: Bool) {
self.isExpand = isExpand
cell.configure(isExpand: isExpand)
self.collectionView.collectionViewLayout.invalidateLayout()
}
}
But I don't know why calling collectionView.reloadItems
works as this unexpectedly. (At first, I wondered if it was a problem caused by the difference between the SectionIdentifierType
and the ItemIdentifierType
of DiffableDatasource
, but the value did not change.)
I simplified the issue as much as possible and posted my full sample code here.