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.

