From 432a9dcaba2dfadb3990f02fb0778aab7214c035 Mon Sep 17 00:00:00 2001 From: Ian Luo Date: Fri, 12 Mar 2021 11:36:38 -0800 Subject: [PATCH] Fix `scrollToItem` appearing underneath sticky header When a `top` scroll position is used, the item will appear underneath the sticky section header. Now, we adjust the frame and use a manual content offset when sticky headers are enabled. When sticky headers are disabled or scrolling to a different position, we call the existing `scrollToItem` function on UICollectionView. --- ListableUI/Sources/ListView/ListView.swift | 35 ++++++++++++++++------ 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/ListableUI/Sources/ListView/ListView.swift b/ListableUI/Sources/ListView/ListView.swift index b14d8b5ea..564dc740c 100644 --- a/ListableUI/Sources/ListView/ListView.swift +++ b/ListableUI/Sources/ListView/ListView.swift @@ -424,27 +424,44 @@ public final class ListView : UIView, KeyboardObserverDelegate } return self.preparePresentationStateForScroll(to: toIndexPath) { - - let isAlreadyVisible: Bool = { - let frame = self.collectionViewLayout.frameForItem(at: toIndexPath) + let itemFrame = self.collectionViewLayout.frameForItem(at: toIndexPath) - return self.collectionView.contentFrame.contains(frame) - }() + let isAlreadyVisible = self.collectionView.contentFrame.contains(itemFrame) // If the item is already visible and that's good enough, return. if isAlreadyVisible && position.ifAlreadyVisible == .doNothing { return } - - animation.perform( - animations: { + + let scroll: () -> Void = { + let sectionHeader = self.collectionViewLayout.layout.content.sections[toIndexPath.section].header + + // Prevent the item from appearing underneath a sticky section header. + + if sectionHeader.isPopulated, + self.collectionViewLayout.layout.stickySectionHeaders, + position.position == .top { + + let itemFrameAdjustedForStickyHeaders = CGRect( + x: itemFrame.minX, + y: itemFrame.minY - sectionHeader.size.height, + width: itemFrame.width, + height: itemFrame.height + ) + self.performScroll(to: itemFrameAdjustedForStickyHeaders, scrollPosition: position) + + } else { self.collectionView.scrollToItem( at: toIndexPath, at: position.position.UICollectionViewScrollPosition, animated: false ) - }, + } + } + + animation.perform( + animations: scroll, completion: completion ) }