Add a simple UIView as header of UICollectionView

2019-01-19 10:41发布

问题:

I have a UICollectionView. I would like to add a header. My header would only be a UILabel. I've :

1) selected "Section Header" as a Collection View accessory in the IB.

2) created a Collection Reusable View in the IB, on the side, declared as collectionViewHeader.

3) added those lines :

- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
    if (kind == UICollectionElementKindSectionHeader) {

            return collectionViewHeader;
    }
    return nil;
}

But they are never called.

Do I have to create a class just for that label in order to use

[self.collectionView registerClass:[UICollectionReusableView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"header"];

?

Why isn't it as simple as the UITableView where you just drag and drop whatever header you want ?! Things are so complicated with UICollectionView...

回答1:

In swift like below

Register Header View

collectionView.registerClass(HeaderView.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "headerView")

In UICollectionViewDataSource

func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView {

    let headerView = collectionView.dequeueReusableSupplementaryViewOfKind(UICollectionElementKindSectionHeader, withReuseIdentifier: "headerView", forIndexPath: indexPath)

    headerView.frame.size.height = 100

    return headerView
}

Important is that you are supply the flow layout with the header size

flowLayout.headerReferenceSize = CGSize(width: self.collectionView.frame.size.width, height: 100)

Otherwise the data source method will not get called



回答2:

If you don't set the header in storyboard, you will have to register it.

In viewDidLoad:

- (void)viewDidLoad
{
    [self.collectionView registerClass:[YourOwnSubClass class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"HeaderView"];
}

But any way, you will have to subclass UICollectionReusableView.

@interface YourOwnSubClass : UICollectionReusableView

then:

- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView
           viewForSupplementaryElementOfKind:(NSString *)kind
                                 atIndexPath:(NSIndexPath *)indexPath
{

    YourOwnSubClass *headerView = [collectionView dequeueReusableSupplementaryViewOfKind:
                                         UICollectionElementKindSectionHeader withReuseIdentifier:@"HeaderView" forIndexPath:indexPath];    
    [self updateSectionHeader:headerView forIndexPath:indexPath];

    return headerView;
}

- (void)updateSectionHeader:(UICollectionReusableView *)header forIndexPath:(NSIndexPath *)indexPath
{
    NSString *text = [NSString stringWithFormat:@"header #%i", indexPath.row];
    header.label.text = text;
}


回答3:

Simply add the view to UICollectionView and change insets

collectionView.addSubview(headerView)
collectionView.contentInset.top = 300

headerView.frame = CGRect(x: 0,
                            y: -300,
                            width: collectionView.frame.size.width,
                            height: 300)