0

I am making an expandable UICollectionViewCell as below. enter image description here Currently, I have registered a UICollectionViewCell named ExpandableCell in CollectionView enter image description here 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.) enter image description here 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)        
    }
}

enter image description here 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.

enter image description here

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.

enter image description here

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.

naljin
  • 439
  • 3
  • 10

0 Answers0