Permitir Una Vista de Encabezado Solo para Ciertas Secciones Usando un iOS UICollectionView


El siguiente código muestra mi vista de encabezado correctamente, pero para cada una de las secciones en la 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;
    }
}

Lo que me gustaría hacer en su lugar, no es mostrar una vista de encabezado para 'Section_One' o 'Section_Two' , sino devolver ' nil 'resulta en una '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;
    }
}

¿Qué debo hacer para mostrar una vista de encabezado solo para ciertas secciones?

Author: Gifreakius, 2014-05-28

5 answers

Siga adelante y devuelva un encabezado para cada sección y luego establezca el tamaño del encabezado de la sección para que tenga un tamaño de cero en esta función 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);
    }
}
 52
Author: mwright,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-29 04:08:16

Tuve un caso con un UICollectionViewController controlando dos UICollectionView s (referenciados más tarde como vista de colección 1 y 2) y quería encabezados a la primera y sin encabezados (o pies de página) a la segunda.

Lo que falta en la respuesta de @mwright es que cuando devuelvas CGSizeZero para vista de colección 2 de la siguiente manera:

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

... significa que el collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView no llamado a todos para vista de colección 2.

Lo que significa que no necesita preocuparse por devolver un encabezado "incorrecto" para la segunda vista colección en vano.

 7
Author: Markus Rautopuro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-19 09:23:06

Me di cuenta de que la respuesta aceptada cuando usaste AutoLayout en el XIB para el encabezado reutilizable.

Estaba especialmente roto si espaciaba el contenido de los bordes o daba a los elementos dentro de la vista de encabezado un tamaño estático e inmutable. Establecer el tamaño del encabezado en CGSizeZero desordenó mi consola de depuración con docenas de advertencias de Interface Builder diciendo que romperían todas las restricciones para cumplir con el requisito establecido en el delegado método.

Si bien eso en sí mismo no es técnicamente un desastre, sigue siendo sucio. Y en la era de Swift y AutoLayout tiene que haber una solución más limpia. Además, nunca quieres enviar ese tipo de cosas a un cliente cuando estás en el trabajo.

Para arreglar esto, en lugar de solo invocar referenceSizeForHeaderInSection: y devolver CGSizeZero creé otra subclase de UICollectionReusableView con XIB y establecí la altura de la vista dentro de ella a 0.

Luego, más tarde, dequeue esa variante fuera de mi switch declaración contenida en el método viewForSupplementaryElementOfKind. ¡Esto satisface los requisitos visuales de Interface Builder y!

Es mejor que tener cientos de advertencias de restricción insatisfactorias impresas en la consola mientras está depurando, de todos modos.

 3
Author: topLayoutGuide,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-17 02:05:41

**

Si devuelve un valor de tamaño (0, 0), no se agrega ningún encabezado.

**

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

}
 1
Author: kamalraj venkatesan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-06 10:33:30

Intente devolver una vista vacía. Probablemente una mejor manera, pero esto podría funcionar....

 -6
Author: Robert Smith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-28 00:25:55