1919
2020@interface IBPUICollectionViewCompositionalLayout () {
2121 NSMutableArray <UICollectionViewLayoutAttributes *> *cachedItemAttributes;
22+ NSMutableDictionary *cachedSupplementaryAttributes;
23+ NSMutableDictionary *cachedDecorationAttributes;
24+ NSMutableArray <UICollectionViewLayoutAttributes *> *layoutAttributesForPinnedSupplementaryItems;
2225
2326 CGRect contentFrame;
2427 NSMutableDictionary <NSNumber *, IBPCollectionViewOrthogonalScrollerSectionController *> *orthogonalScrollerSectionControllers;
@@ -31,6 +34,8 @@ @interface IBPUICollectionViewCompositionalLayout() {
3134
3235@property (nonatomic ) IBPUICollectionLayoutSectionOrthogonalScrollingBehavior parentCollectionViewOrthogonalScrollingBehavior;
3336
37+ @property (nonatomic ) BOOL hasPinnedSupplementaryItems;
38+
3439@end
3540
3641@implementation IBPUICollectionViewCompositionalLayout
@@ -85,6 +90,7 @@ - (instancetype)initWithSectionProvider:(IBPUICollectionViewCompositionalLayoutS
8590
8691- (void )commonInit {
8792 cachedItemAttributes = [[NSMutableArray alloc ] init ];
93+ layoutAttributesForPinnedSupplementaryItems = [[NSMutableArray alloc ] init ];
8894 orthogonalScrollerSectionControllers = [[NSMutableDictionary alloc ] init ];
8995}
9096
@@ -101,6 +107,8 @@ - (void)prepareLayout {
101107 }
102108
103109 [cachedItemAttributes removeAllObjects ];
110+ [layoutAttributesForPinnedSupplementaryItems removeAllObjects ];
111+ self.hasPinnedSupplementaryItems = NO ;
104112
105113 [[orthogonalScrollerSectionControllers allValues ] makeObjectsPerformSelector: @selector (removeFromSuperview )];
106114 [orthogonalScrollerSectionControllers removeAllObjects ];
@@ -109,13 +117,6 @@ - (void)prepareLayout {
109117 if (@available (iOS 11.0 , *)) {
110118 if ([collectionView respondsToSelector: @selector (safeAreaInsets )]) {
111119 collectionContentInset = collectionView.safeAreaInsets ;
112-
113- if (self.scrollDirection == UICollectionViewScrollDirectionVertical) {
114- CGPoint contentOffset = CGPointZero;
115- contentOffset.x = -collectionContentInset.left ;
116- contentOffset.y = -collectionContentInset.top ;
117- collectionView.contentOffset = contentOffset;
118- }
119120 }
120121 }
121122
@@ -411,6 +412,11 @@ - (void)prepareLayout {
411412 contentFrame = CGRectUnion (contentFrame, layoutAttributes.frame );
412413 }
413414 }
415+
416+ if (boundaryItem.pinToVisibleBounds ) {
417+ self.hasPinnedSupplementaryItems = YES ;
418+ [layoutAttributesForPinnedSupplementaryItems addObject: layoutAttributes];
419+ }
414420 }
415421 }
416422}
@@ -466,7 +472,7 @@ - (UICollectionViewLayoutAttributes *)prepareLayoutForBoundaryItem:(IBPNSCollect
466472 }
467473
468474 layoutAttributes.frame = itemFrame;
469- layoutAttributes.zIndex = layoutAttributes .zIndex ;
475+ layoutAttributes.zIndex = boundaryItem .zIndex ;
470476
471477 return layoutAttributes;
472478}
@@ -481,6 +487,9 @@ - (CGSize)collectionViewContentSize {
481487
482488 for (NSInteger i = 0 ; i < cachedItemAttributes.count ; i++) {
483489 UICollectionViewLayoutAttributes *attributes = cachedItemAttributes[i];
490+ if (!CGRectIntersectsRect (attributes.frame , rect)) {
491+ continue ;
492+ }
484493
485494 NSIndexPath *indexPath = attributes.indexPath ;
486495 IBPNSCollectionLayoutItem *layoutItem = [solver layoutItemAtIndexPath: indexPath];
@@ -535,15 +544,48 @@ - (CGSize)collectionViewContentSize {
535544 contentFrame = CGRectUnion (contentFrame, f);
536545
537546 [layoutAttributes addObject: attributes];
538- } else {
539- [layoutAttributes addObject: attributes];
547+ continue ;
548+ }
549+ }
550+ }
551+
552+ [layoutAttributes addObject: attributes];
553+ }
554+
555+ for (NSInteger i = 0 ; i < layoutAttributesForPinnedSupplementaryItems.count ; i++) {
556+ CGPoint contentOffset = self.collectionView .contentOffset ;
557+ UICollectionViewLayoutAttributes *attributes = layoutAttributesForPinnedSupplementaryItems[i];
558+ if (!CGRectIntersectsRect (attributes.frame , rect)) {
559+ continue ;
560+ }
561+
562+ if (@available (iOS 11.0 , *)) {
563+ if ([self .collectionView respondsToSelector: @selector (safeAreaInsets )]) {
564+ if (self.scrollDirection == UICollectionViewScrollDirectionVertical) {
565+ contentOffset.y += self.collectionView .safeAreaInsets .top ;
566+ }
567+ if (self.scrollDirection == UICollectionViewScrollDirectionHorizontal) {
568+ contentOffset.x += self.collectionView .safeAreaInsets .left ;
540569 }
541- } else {
542- [layoutAttributes addObject: attributes];
543570 }
544- } else {
545- [layoutAttributes addObject: attributes];
546571 }
572+
573+ CGPoint nextHeaderOrigin = CGPointMake (INFINITY, INFINITY);
574+
575+ if (i + 1 < layoutAttributesForPinnedSupplementaryItems.count ) {
576+ UICollectionViewLayoutAttributes *nextHeaderAttributes = layoutAttributesForPinnedSupplementaryItems[i + 1 ];
577+ nextHeaderOrigin = nextHeaderAttributes.frame .origin ;
578+ }
579+
580+ CGRect frame = attributes.frame ;
581+ if (self.scrollDirection == UICollectionViewScrollDirectionVertical) {
582+ frame.origin .y = MIN (MAX (contentOffset.y , frame.origin .y ), nextHeaderOrigin.y - CGRectGetHeight (frame));
583+ }
584+ if (self.scrollDirection == UICollectionViewScrollDirectionHorizontal) {
585+ frame.origin .x = MIN (MAX (contentOffset.x , frame.origin .x ), nextHeaderOrigin.x - CGRectGetWidth (frame));
586+ }
587+
588+ attributes.frame = frame;
547589 }
548590
549591 return layoutAttributes;
@@ -553,6 +595,9 @@ - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {
553595 if (!self.collectionView ) {
554596 return NO ;
555597 }
598+ if (self.hasPinnedSupplementaryItems ) {
599+ return YES ;
600+ }
556601
557602 return !CGSizeEqualToSize (newBounds.size , self.collectionView .bounds .size );
558603}
0 commit comments