How to make Supplementary View float in UICollectionView as Section Headers do in UITableView plain style

后端 未结 13 616
逝去的感伤
逝去的感伤 2020-11-27 09:35

I\'m struggling to achieve a \"floating section header\" effect with UICollectionView. Something that\'s been easy enough in UITableView (default b

相关标签:
13条回答
  • 2020-11-27 10:27

    If already set flow layout in Storyboard or Xib file then try this,

    (collectionView.collectionViewLayout as? UICollectionViewFlowLayout)?.sectionHeadersPinToVisibleBounds = true
    
    0 讨论(0)
  • 2020-11-27 10:27

    I ran this with vigorouscoding's code. However that code did not consider sectionInset.

    So I changed this code for vertical scroll

    origin.y = MIN(
                  MAX(contentOffset.y, (CGRectGetMinY(firstCellAttrs.frame) - headerHeight)),
                  (CGRectGetMaxY(lastCellAttrs.frame) - headerHeight)
               );
    

    to

    origin.y = MIN(
               MAX(contentOffset.y, (CGRectGetMinY(firstCellAttrs.frame) - headerHeight - self.sectionInset.top)),
               (CGRectGetMaxY(lastCellAttrs.frame) - headerHeight + self.sectionInset.bottom)
               );
    

    If you guys want code for horizontal scroll, refer to code aove.

    0 讨论(0)
  • 2020-11-27 10:28

    @iPrabu had an excellent answer with sectionHeadersPinToVisibleBounds. I’ll just add that you can set this property in Interface Builder as well:

    1. Select the flow layout object in the document navigator. (If collapsed, expand it first using the toolbar button in the lower-left corner of the editor.)

    1. Open the Identity inspector and add a user-defined runtime attribute with key path sectionHeadersPinToVisibleBounds, type Boolean, and the checkbox checked.

    The default header view has a transparent background. You might want to make it (partially) opaque or add a blur effect view.

    0 讨论(0)
  • 2020-11-27 10:32

    Swift 5.0

    Put the following in your viewDidLoad:

    if let layout = collectionView?.collectionViewLayout as? UICollectionViewFlowLayout {
        layout.sectionHeadersPinToVisibleBounds = true
    }
    
    0 讨论(0)
  • 2020-11-27 10:34

    If you have a single header view that you want pinned to the top of your UICollectionView, here's a relatively simple way to do it. Note this is meant to be as simple as possible - it assumes you are using a single header in a single section.

    //Override UICollectionViewFlowLayout class
    @interface FixedHeaderLayout : UICollectionViewFlowLayout
    @end
    
    @implementation FixedHeaderLayout
    //Override shouldInvalidateLayoutForBoundsChange to require a layout update when we scroll 
    - (BOOL) shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {
        return YES;
    }
    
    //Override layoutAttributesForElementsInRect to provide layout attributes with a fixed origin for the header
    - (NSArray *) layoutAttributesForElementsInRect:(CGRect)rect {
    
        NSMutableArray *result = [[super layoutAttributesForElementsInRect:rect] mutableCopy];
    
        //see if there's already a header attributes object in the results; if so, remove it
        NSArray *attrKinds = [result valueForKeyPath:@"representedElementKind"];
        NSUInteger headerIndex = [attrKinds indexOfObject:UICollectionElementKindSectionHeader];
        if (headerIndex != NSNotFound) {
            [result removeObjectAtIndex:headerIndex];
        }
    
        CGPoint const contentOffset = self.collectionView.contentOffset;
        CGSize headerSize = self.headerReferenceSize;
    
        //create new layout attributes for header
        UICollectionViewLayoutAttributes *newHeaderAttributes = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader withIndexPath:[NSIndexPath indexPathForItem:0 inSection:0]];
        CGRect frame = CGRectMake(0, contentOffset.y, headerSize.width, headerSize.height);  //offset y by the amount scrolled
        newHeaderAttributes.frame = frame;
        newHeaderAttributes.zIndex = 1024;
    
        [result addObject:newHeaderAttributes];
    
        return result;
    }
    @end
    

    See: https://gist.github.com/4613982

    0 讨论(0)
  • 2020-11-27 10:34

    In case anybody is looking for a solution in Objective-C, put this in viewDidload:

        UICollectionViewFlowLayout *flowLayout = 
        (UICollectionViewFlowLayout*)_yourcollectionView.collectionViewLayout;
        [flowLayout setSectionHeadersPinToVisibleBounds:YES];
    
    0 讨论(0)
提交回复
热议问题