How to correctly scroll UICollectionView to a specific section header which has estimated supplementary view height?

73 Views Asked by At

My UICollectionView has multiple sections and has long list of items with supplementary header views. I need to animate to a specific section and show the section header in the view port. Tried to find the location of the section header using best suitable technique like below but because of the header views have different height than estimated initial value, the outcome is not correct. The layoutAttributesForSupplementaryElement uses estimated height when the section is not visible and causing wrong location for contentOffset calculation:

if let sectionHeaderPosition = collectionView.layoutAttributesForSupplementaryElement(
                ofKind: DocType.reuseIdentifier, 
                at: .init(item: 0, section: section)
            ) {
                let offsetY = sectionHeaderPosition.frame.origin.y - collectionView.contentInset.top
               collectionView.setContentOffset(CGPoint(x: 0, y: offsetY), animated: true)
}

Any suggestions?

1

There are 1 best solutions below

0
Tushar On

After trying out many options, posting the best approach that's very close to the expected outcome, might help others.

// 1st step
    collectionView.scrollToItem(at: .init(item: 0, section: section), at: .top, animated: true)
    collectionView.layoutIfNeeded()
// 2nd step
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { [weak self] in
        if let `self` = self,
           let headerPosition = self.collectionView.layoutAttributesForSupplementaryElement(
            ofKind: MyCustomerHeader.reuseIdentifier,
            at: .init(item: 0, section: section)
           ) {
            let headerOffsetY = headerPosition.frame.origin.y - self.collectionView.contentInset.top
            self.collectionView.setContentOffset(
                CGPoint(x: self.collectionView.frame.origin.x, y: headerOffsetY),
                animated: false
            )
        }
    }

Note: every single animation flag (true/flase) and value (i.e 0.3) is very important here, which gave the nearly perfect result.