Skip to content
This repository was archived by the owner on Jun 17, 2023. It is now read-only.

Commit 1b3274d

Browse files
authored
Merge pull request #43 from amirdew/bugfix/selection-update
Keep `viewController.onCurrentPageChanged` when view gets updated
2 parents 8755d4e + 7c584eb commit 1b3274d

3 files changed

+34
-19
lines changed

CollectionViewPagingLayout.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Pod::Spec.new do |s|
22
s.name = "CollectionViewPagingLayout"
3-
s.version = "1.0.0"
3+
s.version = "1.0.1"
44
s.summary = "A simple but highly customizable layout for UICollectionView and SwiftUI."
55

66
s.description = <<-DESC

Lib/CollectionViewPagingLayout.swift

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ public class CollectionViewPagingLayout: UICollectionViewLayout {
8787
private var lastBounds: CGRect?
8888
private var currentViewAnimatorCancelable: ViewAnimatorCancelable?
8989
private var originalIsUserInteractionEnabled: Bool?
90+
private var contentOffsetObservation: NSKeyValueObservation?
9091

9192

9293
// MARK: Public functions
@@ -119,12 +120,14 @@ public class CollectionViewPagingLayout: UICollectionViewLayout {
119120
/// Calls `invalidateLayout` wrapped in `performBatchUpdates`
120121
/// - Parameter invalidateOffset: change offset and revert it immediately
121122
/// this fixes the zIndex issue more: https://stackoverflow.com/questions/12659301/uicollectionview-setlayoutanimated-not-preserving-zindex
122-
public func invalidateLayoutInBatchUpdate(invalidateOffset: Bool = true) {
123+
public func invalidateLayoutInBatchUpdate(invalidateOffset: Bool = false) {
123124
DispatchQueue.main.async { [weak self] in
124-
if invalidateOffset {
125-
let original = self?.collectionView?.contentOffset ?? .zero
126-
self?.collectionView?.contentOffset = .init(x: original.x + 1, y: original.y + 1)
127-
self?.collectionView?.contentOffset = original
125+
if invalidateOffset,
126+
let collectionView = self?.collectionView,
127+
self?.isAnimating == false {
128+
let original = collectionView.contentOffset
129+
collectionView.contentOffset = .init(x: original.x + 1, y: original.y + 1)
130+
collectionView.contentOffset = original
128131
}
129132

130133
self?.collectionView?.performBatchUpdates({ [weak self] in
@@ -268,9 +271,9 @@ public class CollectionViewPagingLayout: UICollectionViewLayout {
268271
let pageSize = scrollDirection == .horizontal ? visibleRect.width : visibleRect.height
269272
let contentSize = scrollDirection == .horizontal ? collectionViewContentSize.width : collectionViewContentSize.height
270273
let maxPossibleOffset = contentSize - pageSize
271-
var offset = pageSize * CGFloat(page)
274+
var offset = Double(pageSize) * Double(page)
272275
offset = max(0, offset)
273-
offset = min(offset, maxPossibleOffset)
276+
offset = min(offset, Double(maxPossibleOffset))
274277
let contentOffset: CGPoint = scrollDirection == .horizontal ? CGPoint(x: offset, y: 0) : CGPoint(x: 0, y: offset)
275278

276279
if animated {
@@ -280,14 +283,18 @@ public class CollectionViewPagingLayout: UICollectionViewLayout {
280283
if animated, let animator = animator {
281284
setContentOffset(with: animator, offset: contentOffset, completion: completion)
282285
} else {
283-
CATransaction.begin()
284-
CATransaction.setCompletionBlock { [weak self] in
285-
self?.isAnimating = false
286-
self?.invalidateLayoutInBatchUpdate()
287-
completion?()
286+
contentOffsetObservation = collectionView?.observe(\.contentOffset, options: [.new]) { [weak self] _, _ in
287+
if self?.collectionView?.contentOffset == contentOffset {
288+
self?.contentOffsetObservation = nil
289+
DispatchQueue.main.async { [weak self] in
290+
self?.invalidateLayoutInBatchUpdate()
291+
self?.collectionView?.setContentOffset(contentOffset, animated: false)
292+
self?.isAnimating = false
293+
completion?()
294+
}
295+
}
288296
}
289297
collectionView?.setContentOffset(contentOffset, animated: animated)
290-
CATransaction.commit()
291298
}
292299

293300
// this is necessary when we want to set the current page without animation
@@ -326,7 +333,7 @@ extension CollectionViewPagingLayout {
326333
boundsObservation = collectionView?.observe(\.bounds, options: [.old, .new, .initial, .prior]) { [weak self] collectionView, _ in
327334
guard collectionView.bounds.size != self?.lastBounds?.size else { return }
328335
self?.lastBounds = collectionView.bounds
329-
self?.invalidateLayoutInBatchUpdate()
336+
self?.invalidateLayoutInBatchUpdate(invalidateOffset: true)
330337
}
331338
}
332339
}

Lib/SwiftUI/PagingCollectionViewControllerBuilder.swift

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,7 @@ public class PagingCollectionViewControllerBuilder<ValueType: Identifiable, Page
5555
viewController.pageViewBuilder = pageViewBuilder
5656
viewController.modifierData = modifierData
5757
viewController.update(list: data, currentIndex: nil)
58-
viewController.onCurrentPageChanged = { [data, selection] in
59-
guard $0 < data.count else { return }
60-
selection?.wrappedValue = data[$0].id
61-
}
58+
setupOnCurrentPageChanged(viewController)
6259
return viewController
6360
}
6461

@@ -68,6 +65,17 @@ public class PagingCollectionViewControllerBuilder<ValueType: Identifiable, Page
6865
}?.offset
6966
viewController.modifierData = modifierData
7067
viewController.update(list: data, currentIndex: selectedIndex)
68+
setupOnCurrentPageChanged(viewController)
69+
}
70+
71+
72+
// MARK: Private functions
73+
74+
private func setupOnCurrentPageChanged(_ viewController: ViewController) {
75+
viewController.onCurrentPageChanged = { [data, selection] in
76+
guard $0 < data.count else { return }
77+
selection?.wrappedValue = data[$0].id
78+
}
7179
}
7280
}
7381
#endif

0 commit comments

Comments
 (0)