web-dev-qa-db-fra.com

Ajouter une simple UIView comme en-tête de UICollectionView

J'ai un UICollectionView. Je voudrais ajouter un en-tête. Mon en-tête ne serait qu'un UILabel. J'ai:

1) a sélectionné "En-tête de section" comme accessoire de vue de collection dans l'IB.

2) a créé une vue réutilisable de collection dans l'IB, sur le côté, déclarée comme collectionViewHeader.

3) a ajouté ces lignes:

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

            return collectionViewHeader;
    }
    return nil;
}

Mais ils ne sont jamais appelés.

Dois-je créer une classe juste pour cette étiquette afin d'utiliser

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

?

Pourquoi n'est-ce pas aussi simple que le UITableView où vous glissez et déposez simplement l'en-tête que vous voulez?! Les choses sont tellement compliquées avec UICollectionView...

30
Nicolas Roy

Dans Swift comme ci-dessous

Enregistrer la vue d'en-tête

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

Dans 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
}

L'important est que vous fournissez la disposition du flux avec la taille de l'en-tête

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

Sinon, la méthode de la source de données ne sera pas appelée

39
Eike

Si vous ne définissez pas la vue d'en-tête dans le storyboard, vous devrez enregistrer nib.

Exemple dans viewDidLoad:

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

Quoi qu'il en soit, vous pouvez également sous-classer UICollectionReusableView.

@interface YourOwnSubClass : UICollectionReusableView

puis appelez délégué dans votre exemple de classe:

- (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;
}

Et n'oubliez pas de définir la taille de l'en-tête dans la vue de la collection ou dans la disposition du flux pour que la vue de l'en-tête soit visible.

20
Raz