UICollectionView with a sticky header

前端 未结 6 446
名媛妹妹
名媛妹妹 2020-12-07 10:13

I found a blog on how to make sticky headers and it works great. Only thing is I don\'t think it takes into account the sectionInserts.

This is how its intended to l

6条回答
  •  -上瘾入骨i
    2020-12-07 11:01

    Fix by Todd Laney to handle Horizontal and Vertical scrolling and to take into account the sectionInsets:

    https://gist.github.com/evadne/4544569

    @implementation StickyHeaderFlowLayout
    
    - (NSArray *) layoutAttributesForElementsInRect:(CGRect)rect {
    
        NSMutableArray *answer = [[super layoutAttributesForElementsInRect:rect] mutableCopy];
    
        NSMutableIndexSet *missingSections = [NSMutableIndexSet indexSet];
        for (NSUInteger idx=0; idx<[answer count]; idx++) {
            UICollectionViewLayoutAttributes *layoutAttributes = answer[idx];
    
            if (layoutAttributes.representedElementCategory == UICollectionElementCategoryCell) {
                [missingSections addIndex:layoutAttributes.indexPath.section];  // remember that we need to layout header for this section
            }
            if ([layoutAttributes.representedElementKind isEqualToString:UICollectionElementKindSectionHeader]) {
                [answer removeObjectAtIndex:idx];  // remove layout of header done by our super, we will do it right later
                idx--;
            }
        }
    
        // layout all headers needed for the rect using self code
        [missingSections enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
            NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:idx];
            UICollectionViewLayoutAttributes *layoutAttributes = [self layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader atIndexPath:indexPath];
            if (layoutAttributes != nil) {
                [answer addObject:layoutAttributes];
            }
        }];
    
        return answer;
    }
    
    - (UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath {
        UICollectionViewLayoutAttributes *attributes = [super layoutAttributesForSupplementaryViewOfKind:kind atIndexPath:indexPath];
        if ([kind isEqualToString:UICollectionElementKindSectionHeader]) {
            UICollectionView * const cv = self.collectionView;
            CGPoint const contentOffset = cv.contentOffset;
            CGPoint nextHeaderOrigin = CGPointMake(INFINITY, INFINITY);
    
            if (indexPath.section+1 < [cv numberOfSections]) {
                UICollectionViewLayoutAttributes *nextHeaderAttributes = [super layoutAttributesForSupplementaryViewOfKind:kind atIndexPath:[NSIndexPath indexPathForItem:0 inSection:indexPath.section+1]];
                nextHeaderOrigin = nextHeaderAttributes.frame.origin;
            }
    
            CGRect frame = attributes.frame;
            if (self.scrollDirection == UICollectionViewScrollDirectionVertical) {
                frame.origin.y = MIN(MAX(contentOffset.y, frame.origin.y), nextHeaderOrigin.y - CGRectGetHeight(frame));
            }
            else { // UICollectionViewScrollDirectionHorizontal
                frame.origin.x = MIN(MAX(contentOffset.x, frame.origin.x), nextHeaderOrigin.x - CGRectGetWidth(frame));
            }
            attributes.zIndex = 1024;
            attributes.frame = frame;
        }
        return attributes;
    }
    
    - (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath {
        UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForSupplementaryViewOfKind:kind atIndexPath:indexPath];
        return attributes;
    }
    - (UICollectionViewLayoutAttributes *)finalLayoutAttributesForDisappearingSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath {
        UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForSupplementaryViewOfKind:kind atIndexPath:indexPath];
        return attributes;
    }
    
    - (BOOL) shouldInvalidateLayoutForBoundsChange:(CGRect)newBound {
        return YES;
    }
    
    @end
    

提交回复
热议问题