@@ -87,6 +87,7 @@ public class CollectionViewPagingLayout: UICollectionViewLayout {
87
87
private var lastBounds : CGRect ?
88
88
private var currentViewAnimatorCancelable : ViewAnimatorCancelable ?
89
89
private var originalIsUserInteractionEnabled : Bool ?
90
+ private var contentOffsetObservation : NSKeyValueObservation ?
90
91
91
92
92
93
// MARK: Public functions
@@ -119,12 +120,14 @@ public class CollectionViewPagingLayout: UICollectionViewLayout {
119
120
/// Calls `invalidateLayout` wrapped in `performBatchUpdates`
120
121
/// - Parameter invalidateOffset: change offset and revert it immediately
121
122
/// 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 ) {
123
124
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
128
131
}
129
132
130
133
self ? . collectionView? . performBatchUpdates ( { [ weak self] in
@@ -268,9 +271,9 @@ public class CollectionViewPagingLayout: UICollectionViewLayout {
268
271
let pageSize = scrollDirection == . horizontal ? visibleRect. width : visibleRect. height
269
272
let contentSize = scrollDirection == . horizontal ? collectionViewContentSize. width : collectionViewContentSize. height
270
273
let maxPossibleOffset = contentSize - pageSize
271
- var offset = pageSize * CGFloat ( page)
274
+ var offset = Double ( pageSize) * Double ( page)
272
275
offset = max ( 0 , offset)
273
- offset = min ( offset, maxPossibleOffset)
276
+ offset = min ( offset, Double ( maxPossibleOffset) )
274
277
let contentOffset : CGPoint = scrollDirection == . horizontal ? CGPoint ( x: offset, y: 0 ) : CGPoint ( x: 0 , y: offset)
275
278
276
279
if animated {
@@ -280,14 +283,18 @@ public class CollectionViewPagingLayout: UICollectionViewLayout {
280
283
if animated, let animator = animator {
281
284
setContentOffset ( with: animator, offset: contentOffset, completion: completion)
282
285
} 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
+ }
288
296
}
289
297
collectionView? . setContentOffset ( contentOffset, animated: animated)
290
- CATransaction . commit ( )
291
298
}
292
299
293
300
// this is necessary when we want to set the current page without animation
@@ -326,7 +333,7 @@ extension CollectionViewPagingLayout {
326
333
boundsObservation = collectionView? . observe ( \. bounds, options: [ . old, . new, . initial, . prior] ) { [ weak self] collectionView, _ in
327
334
guard collectionView. bounds. size != self ? . lastBounds? . size else { return }
328
335
self ? . lastBounds = collectionView. bounds
329
- self ? . invalidateLayoutInBatchUpdate ( )
336
+ self ? . invalidateLayoutInBatchUpdate ( invalidateOffset : true )
330
337
}
331
338
}
332
339
}
0 commit comments