UICollectionView: Make the index fast-scroll to the section header instead of the first section item

We are using a UICollectionView to display a simple list of items sorted alphabetically, with the items starting with each letter in their own section.

To jump to the sections using an index view at the side of the screen, we have implemented the two necessary UICollectionViewDataSource methods:

Issue

Although the correct section does get selected when scrolling through the index view, the top border of the screen is always aligned with the first entry of the selected section. Since we are using sticky header views, this means that the header view, which is also aligned with the top of the screen, overlaps the first entries of each section. This does not look nice and results in unreadable text.

It would be much better to have the section header aligned with the top of the screen, with the first entries following below.

As I understand it is not possible to specify an IndexPath for the header itself, since the header view is not directly part of the UICollectionView. The method UICollectionView.indexPathsForVisibleSupplementaryElements(ofKind:) returns an empty array, so using it did not work either.

Before trying out the built-in methods for iOS 14+, we have been using a third-party view, with which we manually set the content offset to the correct position. While this works, we would prefer to use the built-in approach if possible.

Is there a way to make the index scroll to the section header views?

Did you try to scroll "manually", by the height of the header of section (using scrollToFrame in following code) after reaching the section?

https://stackoverflow.com/questions/36666100/how-to-programmatically-scroll-through-a-collection-view

extension UICollectionView {

        func scrollToNextItem() {
            let scrollOffset = CGFloat(floor(self.contentOffset.x + self.bounds.size.width))
            self.scrollToFrame(scrollOffset: scrollOffset)
        }

        func scrollToPreviousItem() {
            let scrollOffset = CGFloat(floor(self.contentOffset.x - self.bounds.size.width))
            self.scrollToFrame(scrollOffset: scrollOffset)
        }

        func scrollToFrame(scrollOffset : CGFloat) {
            guard scrollOffset <= self.contentSize.width - self.bounds.size.width else { return }
            guard scrollOffset >= 0 else { return }
            self.setContentOffset(CGPoint(x: scrollOffset, y: self.contentOffset.y), animated: true)
        }
    }

with the built-in approach

What do you mean exactly ?

UICollectionView: Make the index fast-scroll to the section header instead of the first section item
 
 
Q