web-dev-qa-db-fra.com

Autoriser une vue d'en-tête pour certaines sections uniquement à l'aide d'un UICollectionView iOS

Le code ci-dessous affiche correctement ma vue d'en-tête, mais pour chacune des sections de l'UICollectionView:

-(UICollectionReusableView *)collectionView:(UICollectionView *)collectionView
          viewForSupplementaryElementOfKind:(NSString *)kind
                                atIndexPath:(NSIndexPath *)indexPath {
    UICollectionReusableView * headerView =
        [collectionView 
            dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader 
                               withReuseIdentifier:@"SectionHeaderCollectionReusableView"
                                      forIndexPath:indexPath];
    switch (indexPath.section) {
        case Section_One:
            return headerView;
        case Section_Two:
            return headerView;
        case Section_Three:
            return headerView;
        case Section_Four:
            return headerView;
        case Section_Five:
            return headerView;

        default:
            return headerView;
    }
}

Ce que je voudrais faire à la place, ce n'est pas afficher une vue d'en-tête pour 'Section_One' ou 'Section_Two', mais retourner 'nil' résulte en une 'NSInternalInconsistencyException':

-(UICollectionReusableView *)collectionView:(UICollectionView *)collectionView
          viewForSupplementaryElementOfKind:(NSString *)kind
                                atIndexPath:(NSIndexPath *)indexPath {
    UICollectionReusableView * headerView =
        [collectionView 
            dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader 
                               withReuseIdentifier:@"SectionHeaderCollectionReusableView"
                                      forIndexPath:indexPath];
    switch (indexPath.section) {
        case Section_One:
            return nil;
        case Section_Two:
            return nil;
        case Section_Three:
            return headerView;
        case Section_Four:
            return headerView;
        case Section_Five:
            return headerView;

        default:
            return nil;
    }
}

Que dois-je faire pour afficher une vue d'en-tête uniquement pour certaines sections?

30
Gifreakius

Allez-y et retournez un en-tête pour chaque section, puis définissez la taille de l'en-tête de section pour avoir une taille nulle dans cette fonction UICollectionViewDelegate.

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section
{
    if (section == 0) {
        return CGSizeZero;
    }else {
        return CGSizeMake(self.collectionView.bounds.size.width, desiredHeight);
    }
}
55
mwright

J'ai eu un cas avec un UICollectionViewController contrôlant deux UICollectionView (référencé plus tard comme vue de collection 1 et 2) et je voulais des en-têtes pour le premier et aucun en-tête (ou pied de page) pour le second.

Ce qui manque dans la réponse de @ mwright, c'est que lorsque vous retournez CGSizeZero pour vue de collection 2 comme suit:

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
    if collectionView == self.collectionView2 {
        return CGSizeZero
    }
    return < something else >
}

... signifie que la collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableViewne le fait pas est appelée du tout pour vue de collection 2.

Cela signifie que vous n'avez pas à vous soucier de retourner un "mauvais" en-tête pour la deuxième vue de collection en vain.

7
Markus Rautopuro

J'ai remarqué que la réponse acceptée a échoué lorsque vous avez utilisé AutoLayout dans le XIB pour l'en-tête réutilisable.

Il était particulièrement cassé si vous espaciez le contenu des bords ou donniez aux éléments à l'intérieur de la vue d'en-tête une taille statique et immuable. La définition de la taille de l'en-tête sur CGSizeZero a encombré ma console de débogage avec des dizaines d'avertissements d'Interface Builder disant qu'ils briseraient toutes les contraintes pour répondre aux exigences définies dans la méthode déléguée.

Bien que cela en soi ne soit pas techniquement une catastrophe, il est toujours sale. Et à l'ère de Swift et AutoLayout, il doit y avoir une solution plus propre. De plus, vous ne voulez jamais envoyer ce genre de chose à un client lorsque vous êtes au travail.

Pour résoudre ce problème, au lieu d'appeler simplement referenceSizeForHeaderInSection: et renvoyant CGSizeZero J'ai créé une autre sous-classe de UICollectionReusableView avec XIB et défini la hauteur de la vue à l'intérieur sur 0.

Plus tard, je supprime cette variante en dehors de mon instruction switch contenue dans la méthode viewForSupplementaryElementOfKind. Cela satisfait à la fois les exigences visuelles de Interface Builder et ! ????

Beats ayant des centaines d'avertissements de contrainte insatisfaisants imprimés dans la console pendant le débogage, de toute façon.

4
topLayoutGuide

**

Si vous retournez une valeur de taille (0, 0), aucun en-tête ne sera ajouté.

**

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {

 switch section {
 case 0:
   return CGSize(width: collectionView.bounds.width, height: 70)
 case 1:
   return CGSize(width: 0, height: 0) // NO HEADER WILL BE ADDED
 case 2:
   return CGSize(width: collectionView.bounds.width, height: 70)
 case 3:
   return CGSize(width: 0, height: 0) // NO HEADER WILL BE ADDED
 default:
   return CGSize(width: collectionView.bounds.width, height: 70)
 }

}
2