Skip to content

Commit

Permalink
bottomToTop scrollOffset preservation (#121)
Browse files Browse the repository at this point in the history
* bottomToTop scrollOffset preservation

When using the `bottomToTop` layoutDirection, we should preserve scroll position relative to the bottom of the collection view whenever we change bounds.

* fix formating

---------

Co-authored-by: Elfred Pagan <elfred.pagan@airbnb.com>
  • Loading branch information
elfredpagan and Elfred Pagan committed Mar 5, 2024
1 parent 2d0d4f9 commit e1b983f
Showing 1 changed file with 27 additions and 5 deletions.
32 changes: 27 additions & 5 deletions MagazineLayout/Public/MagazineLayout.swift
Original file line number Diff line number Diff line change
Expand Up @@ -586,11 +586,25 @@ public final class MagazineLayout: UICollectionViewLayout {
}

override public func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
let isSameWidth = collectionView?.bounds.size.width.isEqual(
to: newBounds.size.width,
threshold: 1 / scale)
?? false
return !isSameWidth || hasPinnedHeaderOrFooter
// When using the topToBottom layout direction, we only want to invalidate the layout when the
// widths differ. When using the bottomToTop layout direction, we want to invalidate on any
// size change due to the requirement of needing to preserve scroll position from the bottom
var shouldInvalidateDueToSize = false
switch verticalLayoutDirection {
case .topToBottom:
shouldInvalidateDueToSize = !currentCollectionView.bounds.size.width.isEqual(
to: newBounds.size.width,
threshold: 1 / scale)
case .bottomToTop:
shouldInvalidateDueToSize = !(currentCollectionView.bounds.size.width.isEqual(
to: newBounds.size.width,
threshold: 1 / scale) &&
currentCollectionView.bounds.size.height.isEqual(
to: newBounds.size.height,
threshold: 1 / scale))
}

return shouldInvalidateDueToSize || hasPinnedHeaderOrFooter
}

override public func invalidationContext(
Expand All @@ -605,6 +619,14 @@ public final class MagazineLayout: UICollectionViewLayout {
height: newBounds.height - currentCollectionView.bounds.height)
invalidationContext.invalidateLayoutMetrics = false

// If our layout direction is bottom to top we want to adjust scroll position relative to the
// bottom
if case .bottomToTop = verticalLayoutDirection {
invalidationContext.contentOffsetAdjustment = CGPoint(
x: 0.0,
y: currentCollectionView.bounds.height - newBounds.height)
}

return invalidationContext
}

Expand Down

0 comments on commit e1b983f

Please sign in to comment.