Comment masquer le premier en-tête de section dans UITableView (style groupé)


108

Comme la conception des vues de tableau utilisant le style groupé a considérablement changé avec iOS 7, je voudrais masquer (ou supprimer) le premier en-tête de section. Jusqu'à présent, je n'ai pas réussi à y parvenir.

Un peu simplifié, mon code ressemble à ceci:

- (CGFloat) tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    if (section == 0)
        return 0.0f;
    return 32.0f;
}

- (UIView*) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    if (section == 0) {
        UIView* view = [[UIView alloc] initWithFrame: CGRectMake(0.0f, 0.0f, 640.0f, 0.0f)];
        return view;
    }
    return nil;
}

- (NSString*) tableView:(UITableView *) tableView titleForHeaderInSection:(NSInteger)section
{
    if (section == 0) {
        return nil;
    } else {
        // return some string here ...
    }
}

Si je renvoie une hauteur de 0, les deux autres méthodes ne seront jamais appelées avec l'index de section 0. Pourtant, un en-tête de section vide est toujours dessiné avec la hauteur par défaut. (Dans iOS 6, les deux méthodes sont appelées. Cependant, le résultat visible est le même.)

Si je renvoie une valeur différente, l'en-tête de section obtient la hauteur spécifiée.

Si je renvoie 0,01, c'est presque correct. Cependant, lorsque j'active "Couleur des images mal alignées" dans le simulateur, cela marque toutes les cellules de la vue tableau (ce qui semble être une conséquence logique).

Les réponses à la question UITableView: masquer l'en-tête de la section vide semblent indiquer que certaines personnes ont réussi à masquer l'en-tête de la section. Mais cela peut s'appliquer au style simple (au lieu du style groupé).

Le meilleur compromis jusqu'à présent est de renvoyer la hauteur 0,5, ce qui donne une ligne un peu plus épaisse sous la barre de navigation. Cependant, j'apprécierais que quelqu'un sache comment le premier en-tête de section peut être complètement caché.

Mettre à jour

Selon l' analyse de caglar ( https://stackoverflow.com/a/19056823/413337 ), le problème ne survient que si la vue de table est contenue dans un contrôleur de navigation.


Je n'ai pas obtenu cette partie => if (section == 0) return view; retour nul; c'est-à-dire renvoyer une vue quand c'est la première section et nulle sinon?
Zen

L'idée est de renvoyer une vue avec une hauteur de 0 pour la première section et de renvoyer nil pour toutes les autres sections afin que la vue de table utilise la vue d'en-tête par défaut pour elles. La partie nulle fonctionne bien; la vue de table montre un en-tête pour ces sections. Mais la partie de la section 0 n'est pas pertinente car la méthode n'est jamais appelée avec section == 0.
Codo du

1
Cette réponse semble courte et douce. stackoverflow.com/a/23955420/3965
Mr Rogers

Réponses:


154

J'ai une solution de contournement qui me semble raisonnablement propre. Alors je réponds à ma propre question.

Puisque 0 comme hauteur de l'en-tête de la première section ne fonctionne pas, je retourne 1. Ensuite, j'utilise le contentInset pour masquer cette hauteur sous la barre de navigation.

Objectif c:

- (CGFloat) tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    if (section == 0)
            return 1.0f;
    return 32.0f;
}

- (NSString*) tableView:(UITableView *) tableView titleForHeaderInSection:(NSInteger)section
{
    if (section == 0) {
        return nil;
    } else {
        // return some string here ...
    }
}

- (void) viewDidLoad
{
    [super viewDidLoad];

     self.tableView.contentInset = UIEdgeInsetsMake(-1.0f, 0.0f, 0.0f, 0.0);
}

Rapide:

override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return section == 0 ? 1.0 : 32
}

override func viewDidLoad() {
    super.viewDidLoad()

    tableView.contentInset = UIEdgeInsets(top: -1, left: 0, bottom: 0, right: 0)
}

6
Utiliser une hauteur d'en-tête de 0,1f est encore mieux pour le cacher.
Chuck Krutsinger

4
J'ai essayé d'utiliser 0.1f. Mais le résultat est que les dessins ne sont plus alignés sur les pixels, ce qui provoque des flous et réduit les performances. Essayez-le simplement dans le simulateur: il a une option pour mettre en évidence l'alignement problématique.
Codo

31
En fait, une meilleure implémentation (moins susceptible de se rompre à l'avenir) consiste à utiliser CGFLOAT_MINau lieu d'une valeur codée en dur. En d'autres termes, ne le faites pas return 1.0fou à la 0.1fplace, return CGFLOAT_MINsi Apple change un jour la valeur minimale acceptable, vous aurez du code à changer si vous codez en dur la valeur de retour. De plus, vous ne savez déjà pas si vous utilisez la plus petite valeur possible. En utilisant la constante définie, vous êtes assuré d'utiliser la plus petite valeur possible et votre code survivra aux modifications du système d'exploitation.
Chris Ostmo

11
@Chris: J'ai bien peur que vous n'ayez pas compris l'idée. Je ne renvoie pas une très petite valeur mais un multiple de la taille d'un pixel pour que le dessin reste aligné sur les pixels (pour de bonnes performances et une netteté). Je le compense ensuite en utilisant l'encart de contenu. Il est peu probable que cela change à l'avenir car il s'agit d'une distance considérable et visible et non pas quelque chose que le système d'exploitation pourrait ignorer.
Codo

8
+1 Pour ne pas utiliser de valeurs de pixel fractionnaires comme décalages d'interface utilisateur.
Ricardo Sanchez-Saez

52

Voici comment masquer le premier en-tête de section dans UITableView (style groupé).

Solution Swift 3.0 et Xcode 8.0

  1. Le délégué de TableView doit implémenter la méthode heightForHeaderInSection

  2. Dans la méthode heightForHeaderInSection, renvoie le nombre le moins positif. (pas zéro!)

    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    
        let headerHeight: CGFloat
    
        switch section {
        case 0:
            // hide the header
            headerHeight = CGFloat.leastNonzeroMagnitude
        default:
            headerHeight = 21
        }
    
        return headerHeight
    }

6
retourner CGFloat.leastNonzeroMagnitude au lieu de 0 m'a aidé. Merci!
anoo_radha

Réponse parfaite, merci
Pierre

À propos, CGFLOAT_MINpour objc est identique à CGFloat.leastNonzeroMagnitudedans Swift
DawnSong

36

La réponse était très drôle pour moi et mon équipe et a fonctionné comme un charme

  • Dans le générateur d'interface, déplacez simplement la vue de table sous une autre vue dans la hiérarchie des vues.

RAISON:

Nous avons observé que cela se produit uniquement pour la première vue dans la hiérarchie des vues, si cette première vue est un UITableView . Donc, tous les autres UITableViews similaires n'ont pas cette section ennuyeuse, sauf la première. Nous avons essayé de déplacer UITableView de la première place dans la hiérarchie des vues, et tout fonctionnait comme prévu.


1
Avez-vous toujours l'effet de verre dépoli de la barre de navigation lorsque vous faites défiler la vue du tableau?
Codo du

Vous aurez cet effet de flou lorsque vous configurerez votre tableView en conséquence. Vous devrez contentInsetpar exemple définir le sur pour {0, 64, 0, 0}avoir le décalage de 64 pixels par rapport au haut (barre d'état plus barre de navigation). Le tableView doit être attaché en haut de l'écran, pas le topLayoutGuide (pour le laisser atteindre sous la barre de navigation)
Julian F. Weinert

Si vous n'utilisez pas pull pour actualiser, cela semble parfait.
Michael

2
Sensationnel. Cela a fonctionné pour moi dans iOS 9 et m'a époustouflé.
allouer

Cela devrait être la réponse acceptée. Un bug tellement étrange!
Oded Harth

25

Utilisez cette astuce pour la table de type groupé

Copiez-collez le code ci-dessous pour votre vue de table dans la méthode viewDidLoad :

tableView.tableHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, tableView.bounds.size.width, 0.01f)];

Je ne l'ai pas essayé mais je soupçonne que cette solution présente le même inconvénient que certaines des autres solutions proposées: les dessins ne sont plus alignés sur les pixels, ce qui provoque des flous et réduit les performances. Le simulateur peut le révéler: il dispose d'une option pour mettre en évidence l'alignement problématique. Cependant, s'il arrondit à 0, alors c'est une bonne solution.
Codo

Oui, je suppose qu'il est arrondi à 0. Parce que je l'ai utilisé plusieurs fois, mais je n'ai trouvé aucun flou dans les dessins.
Nitesh Borad

TableHeaderView et vue d'en-tête de section? quelle est la différence,
AsifHabib

Ou légèrement plus courte: _tableView.tableHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 1)].
mojuba

@AsifHabib: tableHeaderView est placé en haut de tous les éléments du tableau. C'est la vue d'en-tête de la table elle-même. Et la vue d'en-tête de section est une vue à placer sur chaque section. Il peut y avoir de nombreuses vues d'en-tête de section selon le nombre spécifié de sections dans le tableau. Mais, il n'y aura qu'une seule vue d'en-tête de table.
Nitesh Borad

21

cette façon est OK.

override func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    if section == 0 {
        return CGFloat.min
    }
    return 25
}

override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    if section == 0 {
        return nil
    }else {
        ...
    }
}

2
C'est une belle variation de ma solution sauf qu'elle utilise des valeurs fractionnaires. De cette façon, le texte et les images ne sont plus alignés sur les pixels, le dessin est ralenti et le résultat peut devenir flou. Le simulateur dispose de l'option "Couleur des images mal alignées" pour révéler ce problème.
Codo

Fonctionne très bien pour les gens comme moi utilisant des cellules statiques avec un containerView
thibaut noah

3
Swift 3> 'CGFloat.min' a été renommé en 'CGFloat.leastNormalMagnitude'
rjobidon

6

J'ai juste copié votre code et essayé. Il fonctionne normalement (essayé en simulateur). J'ai joint la vue des résultats. Vous voulez une telle vue, non? Ou j'ai mal compris votre problème?

entrez la description de l'image ici


1
Oui, c'est essentiellement ce que je veux, sauf que ma vue de table est dans un contrôleur de navigation. Cela pourrait-il faire la différence?
Codo du

2
J'ai ajouté tableView au contrôleur de navigation et votre situation apparaît :) Je pense que dans iOS 7, cette hauteur d'en-tête corrige par défaut dans la vue de tableau de style groupé. En changeant le cadre de tableView, la première vue d'en-tête peut être masquée (comme set x = 0 y = -40). Cependant, je sais que cette solution n'est pas une bonne solution.
caglar le

1
Merci beaucoup pour votre travail. Il semble donc que le problème ne se pose que si la vue de table utilise le style groupé et est contenue dans un contrôleur de navigation.
Codo du

En essayant de passer de viewcontroller à tableviewcontroller, je n'ai pas pu résoudre le problème avec l'en-tête. Il me manque peut-être quelque chose en essayant de le convertir. (iOS 7.0.3 sim)
Evgeni Petrov

1
Ce problème apparaît également dans cet instantané! la 0ème cellule ne part pas de x: 0.0f & y: 0.0f.
Burhanuddin Sunelwala

6

Swift3: heightForHeaderInSection fonctionne avec 0, il vous suffit de vous assurer que l'en-tête est défini sur clipsToBounds.

func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
       return 0
}

si vous ne définissez pas l'en-tête masqué clipsToBounds, il sera visible lors du défilement.

func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
    guard let header = view as? UITableViewHeaderFooterView else { return }

    header.clipsToBounds = true
}

1
clipsToBound = true est très important si vous prévoyez de masquer complètement la vue d'en-tête de section. Définir sa hauteur sur 0 / CGFLOAT_MIN ne suffit pas.
Altimac

5

Mise à jour [19/09/17]: l'ancienne réponse ne fonctionne plus pour moi dans iOS 11. Merci Apple. Ce qui suit a fait:

self.tableView.sectionHeaderHeight = UITableViewAutomaticDimension;
self.tableView.estimatedSectionHeaderHeight = 20.0f;
self.tableView.contentInset = UIEdgeInsetsMake(-18.0, 0.0f, 0.0f, 0.0);

Réponse précédente:

Comme indiqué dans les commentaires de Chris Ostomo, ce qui suit a fonctionné pour moi:

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    return CGFLOAT_MIN; // to get rid of empty section header
}

Je soupçonne que le contenu de votre vue de tableau n'est plus aligné sur les pixels, ce qui provoque des flous et réduit les performances. Le simulateur peut le révéler: il dispose d'une option pour mettre en évidence l'alignement problématique. Cependant, s'il arrondit à 0, alors c'est une bonne solution.
Codo le

Non, je n'ai remarqué aucun problème de contenu. Les contraintes semblaient bien.
Manindra Moharana du

1
Welp! Ne fonctionne plus sous iOS 11! Mon correctif a duré moins d'une semaine .. 😞
Manindra Moharana

4

Voici comment se débarrasser de l'en-tête de section supérieur dans un UITableView groupé, dans Swift:

tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: CGFloat.leastNormalMagnitude))

3

Dans Swift 4.2 et de nombreuses versions antérieures, au lieu de définir la hauteur du premier en-tête à 0 comme dans les autres réponses, vous pouvez simplement définir les autres en-têtes sur nil. Supposons que vous ayez deux sections et que vous ne souhaitiez que la seconde (c'est-à-dire 1) avoir un en-tête. Cet en-tête contiendra le texte Foobar :

override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    return section == 1 ? "Foobar" : nil
}

3

Essayez ceci si vous souhaitez supprimer complètement tous les en-têtes de section

func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return CGFloat.leastNormalMagnitude
}

func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
    return CGFloat.leastNormalMagnitude
}

C'est juste dont j'ai besoin. Une solution simple et facile. 1+
iGhost

0

Je ne peux pas encore commenter mais j'ai pensé ajouter que si vous avez un UISearchControllersur votre contrôleur avec UISearchBarcomme vôtre tableHeaderView, définir la hauteur de la première section sur 0 dans heightForHeaderInSectionfonctionne effectivement.

J'utilise self.tableView.contentOffset = CGPointMake(0, self.searchController.searchBar.frame.size.height);pour que la barre de recherche soit masquée par défaut.

Le résultat est qu'il n'y a pas d'en-tête pour la première section, et le défilement vers le bas affichera la barre de recherche juste au-dessus de la première ligne.


0

le plus simple est de loin de retourner nil, ou ""dans func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String?une section où vous ne souhaitez pas afficher l'en-tête.


0

Version Swift: Swift 5.1 La
plupart du temps, vous pouvez définir la hauteur dans le délégué tableView comme ceci:

func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
   return UIView(frame: CGRect(x: 0, y: 0, width: view.width, height: CGFloat.leastNormalMagnitude))
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
   return CGFloat.leastNormalMagnitude
}

Parfois, lorsque vous avez créé UITableView avec Xib ou Storyboard, la réponse de up ne fonctionne pas. vous pouvez essayer la deuxième solution:

let headerView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: CGFloat.leastNormalMagnitude))
self.tableView.tableHeaderView = headerView

J'espère que ça marche pour toi!

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.