Est-il possible de désactiver les en-têtes flottants dans UITableView avec UITableViewStylePlain?

177

J'utilise un UITableViewpour mettre en page des «pages» de contenu. J'utilise les en- têtes de la vue de la table pour la mise en page de certaines images , etc. , et je préférerais que si elles ne flottent pas mais est resté statique comme ils le font quand le style est réglé sur UITableViewStyleGrouped.

Autre que l'utilisation UITableViewStyleGrouped, y a-t-il un moyen de le faire? Je voudrais éviter d'utiliser grouped car il ajoute une marge vers le bas de toutes mes cellules et nécessite la désactivation de la vue d'arrière-plan pour chacune des cellules. J'aimerais avoir le contrôle total de ma mise en page. Idéalement, ce serait un "UITableViewStyleBareBones", mais je n'ai pas vu cette option dans la documentation ...

Merci beaucoup,

Rusé
la source
59
Utilisez le style de tableau UITableViewStyleGrouped - c'est la réponse pour tous ceux qui recherchent la désactivation des en-têtes flottants et ne lisent pas toute la question (cela m'est arrivé ...).
Joe moyen du
@Kasztan C'est une solution zéro ligne qui fonctionne très bien! Merci.
Lee Fastenau

Réponses:

27

Vous devriez pouvoir simuler cela en utilisant une cellule personnalisée pour faire vos lignes d'en-tête. Ceux-ci défileront ensuite comme n'importe quelle autre cellule de la vue tableau.

Il vous suffit d'ajouter une logique dans votre cellForRowAtIndexPathpour renvoyer le bon type de cellule lorsqu'il s'agit d'une ligne d'en-tête.

Vous devrez probablement gérer vos sections vous-même, c'est-à-dire avoir tout dans une section et simuler les en-têtes. (Vous pouvez également essayer de renvoyer une vue masquée pour la vue d'en-tête, mais je ne sais pas si cela fonctionnera)

Frankodwyer
la source
11
Ouais ... cela semble un peu un hack cependant. Cela semble être un oubli de la part d'Apple, car il est clair que le code est là pour le faire, nous avons juste besoin de pouvoir définir un drapeau.
Tricky le
2
Vérifiez ma réponse ci-dessous pour la bonne façon d'obtenir l'effet sans aucun hack spécial, il suffit de gérer la première cellule de chaque section comme son en-tête de section!
Sumit Anantwar
338

Un moyen probablement plus simple d'y parvenir:

Objectif c:

CGFloat dummyViewHeight = 40;
UIView *dummyView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.tableView.bounds.size.width, dummyViewHeight)];
self.tableView.tableHeaderView = dummyView;
self.tableView.contentInset = UIEdgeInsetsMake(-dummyViewHeight, 0, 0, 0);

Rapide:

let dummyViewHeight = CGFloat(40)
self.tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: self.tableView.bounds.size.width, height: dummyViewHeight))
self.tableView.contentInset = UIEdgeInsetsMake(-dummyViewHeight, 0, 0, 0)

Les en-têtes de section défileront désormais comme n'importe quelle cellule normale.

samvermette
la source
5
Ce friggin fonctionne comme un charme !! La présence d'un en-tête de vue d'en-tête de table empêche les en-têtes de section de flotter. Et un en-tête invisible avec des encarts de contenu appropriés pour le tableau fait l'affaire. Merci beaucoup! Je me demande pourquoi cette réponse n'attire pas beaucoup d'attention
Shyam Bhat
4
N'y croyez toujours pas! Pas d'API privées, pas de fouille dans les classes, rien! Je suis confronté à ce problème depuis des lustres et j'ai ajouté des vues de table au-dessus des vues de défilement (avec le défilement de la vue de table désactivé), ce qui ferait défiler les en-têtes de table normalement. mais j'ai juste commencé à chercher si Apple a fourni de nouvelles méthodes dernièrement pour résoudre ce problème .. tellement heureux que je suis tombé sur votre réponse. merci encore
Shyam Bhat
13
le seul inconvénient que j'ai vu est que l'en-tête supérieur ne sera plus affiché (vous ne pouvez le voir qu'en faisant défiler vers le haut). Au moins pour moi il n'est pas montré
Ruzard
5
Vous pouvez toujours afficher le tableHeaderView de la table en augmentant sa hauteur en haut, d'un nombre égal à la hauteur de l'en-tête de section et en réduisant l'encart de contenu du même nombre.
Shyam Bhat
2
J'aurais aimé pouvoir à nouveau voter pour cela, je suis assez certain que c'est au moins la troisième fois que je me retrouve sur cette question et cela a résolu mon problème.
Ell Neal
252

(Pour ceux qui sont arrivés ici en raison d'un mauvais style de tableau) Changez le style de tableau de simple à groupé, via l'inspecteur d'attributs ou via le code:

let tableView = UITableView(frame: .zero, style: .grouped)
David72
la source
3
Ceci est exactement ce que je cherchais. Merci!
ninjudd
4
"Autre que l'utilisation de UITableViewStyleGrouped, y a-t-il un moyen de le faire?"
Michael Peterson
27
Heureusement que j'ai appris à vérifier toutes les réponses avant de mettre en œuvre la plus votée :)
Tung Fam
1
Maintenant, ce gars, est la réponse que vous cherchiez. Sachez que vous pouvez également trouver la TableView Stylepropriété dans AttributesInspector.
Cristian Holdunu
4
La question mentionne spécifiquement de chercher un moyen "Autre puis utilisant UITableViewStyleGrouped"
Ferdz
73

ATTENTION : cette solution implémente une méthode API réservée. Cela pourrait empêcher l'application d'être approuvée par Apple pour distribution sur l'AppStore.

J'ai décrit les méthodes privées qui transforment les en-têtes de section flottant dans mon blog

En gros, il vous suffit de sous UITableView- classer et de retourner NOdans deux de ses méthodes:

- (BOOL)allowsHeaderViewsToFloat;
- (BOOL)allowsFooterViewsToFloat;
cale
la source
40
Une réponse ne mérite pas un vote défavorable simplement parce qu'elle fait référence à des API privées (tout le monde n'écrit pas de code à soumettre à l'AppStore). C'est doublement vrai lorsque la réponse se trouve être correcte. Le sous-classement (ou, plus facilement, la création d'une catégorie UITableView) qui retourne NO pour ces méthodes empêche les en-têtes de flotter. Si vous souhaitez voir ce ajouté comme une API publique, déposer un rapport s'il vous plaît bug: bugreport.apple.com
jemmons
5
Si nous implémentons cette fonction dans une application, comment Apple se rendrait-il compte que vous utilisez une API privée? D'après tout ce qu'ils savent, je viens d'implémenter une méthode dans une sous-classe de UITableView, et ils ne peuvent même pas voir cela sans désassembler le code, et ce ne serait pas si facile. Ce n'est pas APPELER une méthode dans une API privée, c'est juste en implémenter une ....
Javier Soto
3
@jemmons si vous ne voulez pas que je décline votre réponse, marquez-la comme "API privée est utilisée ici". Sort of disclaimer :)
kas-kad
2
Votre lien "mon blog" est rompu
MartinMoizard
12
@jemmons "tout le monde n'écrit pas de code à soumettre à l'AppStore" L'Appstore n'est pas vraiment le problème. Le problème est qu'Apple peut modifier les API privées sans communiquer ni abandonner, ce qui cassera votre application. C'est une meilleure raison pour laquelle vous ne devriez pas utiliser d'API privées que d'être rejeté par Apple
aryaxt
29

Ok, je sais qu'il est tard mais je devais le faire. J'ai passé 10 heures à rechercher une solution fonctionnelle mais je n'ai pas trouvé de réponse complète. J'ai trouvé des indices mais difficile à comprendre pour les débutants. J'ai donc dû mettre mes 2 cents et compléter la réponse.

Comme cela a été suggéré dans quelques-unes des réponses, la seule solution de travail que j'ai pu mettre en œuvre est d'insérer des cellules normales dans la vue de tableau et de les gérer comme des en-têtes de section, mais le meilleur moyen d'y parvenir est d'insérer ces cellules à ligne 0 de chaque section. De cette façon, nous pouvons gérer très facilement ces en-têtes non flottants personnalisés.

Donc, les étapes sont.

  1. Implémentez UITableView avec le style UITableViewStylePlain.

    -(void) loadView
    {
        [super loadView];
    
        UITableView *tblView =[[UITableView alloc] initWithFrame:CGRectMake(0, frame.origin.y, frame.size.width, frame.size.height-44-61-frame.origin.y) style:UITableViewStylePlain];
        tblView.delegate=self;
        tblView.dataSource=self;
        tblView.tag=2;
        tblView.backgroundColor=[UIColor clearColor];
        tblView.separatorStyle = UITableViewCellSeparatorStyleNone;
    }
  2. Implémentez titleForHeaderInSection comme d'habitude (vous pouvez obtenir cette valeur en utilisant votre propre logique, mais je préfère utiliser des délégués standard).

    - (NSString *)tableView: (UITableView *)tableView titleForHeaderInSection:(NSInteger)section
    {
        NSString *headerTitle = [sectionArray objectAtIndex:section];
        return headerTitle;
    }
  3. Immplement numberOfSectionsInTableView comme d'habitude

    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 
    {
        int sectionCount = [sectionArray count];
        return sectionCount;
    }
  4. Implémentez numberOfRowsInSection comme d'habitude.

    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
    {
        int rowCount = [[cellArray objectAtIndex:section] count];
        return rowCount +1; //+1 for the extra row which we will fake for the Section Header
    }
  5. Renvoie 0.0f dans heightForHeaderInSection.

    - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
    {
        return 0.0f;
    }
  6. N'implémentez PAS viewForHeaderInSection. Supprimez complètement la méthode au lieu de renvoyer nil.

  7. Dans heightForRowAtIndexPath. Vérifiez si (indexpath.row == 0) et renvoyez la hauteur de cellule souhaitée pour l'en-tête de section, sinon renvoyez la hauteur de la cellule.

    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        if(indexPath.row == 0)
        {
            return 80; //Height for the section header
        }
        else
        {
            return 70; //Height for the normal cell
        }
    }
  8. Maintenant, dans cellForRowAtIndexPath, vérifiez si (indexpath.row == 0) et implémentez la cellule comme vous voulez que l'en-tête de section soit et définissez le style de sélection sur aucun. ELSE implémentez la cellule comme vous le souhaitez.

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        if (indexPath.row == 0)
        {
            UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"SectionCell"];
            if (cell == nil)
            {
                cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"SectionCell"] autorelease];
                cell.selectionStyle = UITableViewCellSelectionStyleNone; //So that the section header does not appear selected
    
                cell.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"SectionHeaderBackground"]];
            }
    
            cell.textLabel.text = [tableView.dataSource tableView:tableView titleForHeaderInSection:indexPath.section];
    
            return cell;
        }
        else
        {
            UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
    
            if (cell == nil) 
            {
                cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"] autorelease];
                cell.selectionStyle = UITableViewCellSelectionStyleGray; //So that the normal cell looks selected
    
                cell.backgroundView =[[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"CellBackground"]]autorelease];
                cell.selectedBackgroundView=[[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"SelectedCellBackground"]] autorelease];
            }
    
            cell.textLabel.text = [[cellArray objectAtIndex:indexPath.section] objectAtIndex:indexPath.row -1]; //row -1 to compensate for the extra header row
    
            return cell;
        }
    }
  9. Maintenant, implémentez willSelectRowAtIndexPath et retournez nil si indexpath.row == 0. Cela garantira que didSelectRowAtIndexPath ne sera jamais déclenché pour la ligne d'en-tête Section.

    - (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
    {
        if (indexPath.row == 0)
        {
            return nil;
        }
    
        return indexPath;
    }
  10. Et enfin dans didSelectRowAtIndexPath, vérifiez si (indexpath.row! = 0) et continuez.

    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    {
        if (indexPath.row != 0)
        {
            int row = indexPath.row -1; //Now use 'row' in place of indexPath.row
    
            //Do what ever you want the selection to perform
        }
    }

Avec cela, vous avez terminé. Vous avez maintenant un en-tête de section parfaitement défilant et non flottant.

Sumit Anantwar
la source
1
Implémentation de 'willSelectRowAtIndexPath' afin que le contrôle n'atteigne jamais 'didSelectRowAtIndexPath' lors de la sélection de la ligne d'en-tête de section.
Sumit Anantwar
En fait, je plie + déplie les lignes lorsque l'en-tête est sélectionné. Mais bon de savoir que vous pouvez le faire
Yariv Nissim
Bonne réponse, mais pourquoi le 'if (indexPath.row! = 0)' enregistre 'didSelectRowAtIndexPath'? Est-ce juste pour être plus sûr? La ligne ne peut jamais être 0 avec votre implémentation 'willSelectRowAtIndexPath', non?
Glenn85
1
@ Glenn85, Désolé pour la réponse tardive. Oui, c'est juste pour une sécurité supplémentaire.
Sumit Anantwar
28

Dans votre Interface Builder, cliquez sur votre problème Vue de table

vue de la table des problèmes

Ensuite, accédez à l'inspecteur d'attributs et changez Style simple en groupé;) Facile

facile

HannahCarney
la source
17

La chose intéressante à propos de UITableViewStyleGrouped est que la tableView ajoute le style aux cellules et non au TableView.

Le style est ajouté en tant que backgroundView aux cellules en tant que classe appelée UIGroupTableViewCellBackground qui gère le dessin d'un arrière-plan différent en fonction de la position de la cellule dans la section.

Une solution très simple sera donc d'utiliser UITableViewStyleGrouped, de définir backgroundColor du tableau sur clearColor, et de simplement remplacer le backgroundView de la cellule dans cellForRow:

cell.backgroundView = [[[UIView alloc] initWithFrame:cell.bounds] autorelease];
adamsiton
la source
1
Cela devrait être la meilleure réponse. Il y a un article de blog à ce sujet ici: corecocoa.wordpress.com/2011/09/17/…
Sam
Cette solution ne fonctionne pas vraiment. Je continue à avoir un espace supplémentaire autour des cellules autour. Une idée ?
gsempe
2
Le contentView des cellules ne serait-il pas toujours décalé vers la droite?
Piotr Tomasik
15

Changez votre style TableView:

self.tableview = [[UITableView alloc] initwithFrame:frame style:UITableViewStyleGrouped];

Selon la documentation Apple pour UITableView:

UITableViewStylePlain - Une vue de table simple. Tous les en-têtes ou pieds de page de section sont affichés sous forme de séparateurs en ligne et flottent lorsque la vue de tableau est défilée.

UITableViewStyleGrouped - Une vue de table dont les sections présentent des groupes distincts de lignes. Les en-têtes et pieds de page de section ne flottent pas.

Aks
la source
5

Il existe un autre moyen délicat. L'idée principale est de doubler le numéro de section, et le premier n'affiche que l'en-têteView tandis que le second montre les cellules réelles.

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return sectionCount * 2;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    if (section%2 == 0) {
        return 0;
    }
    return _rowCount;
}

Ce qu'il faut alors faire est d'implémenter les délégués headerInSection:

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    if (section%2 == 0) {
        //return headerview;
    }
    return nil;
}

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
    if (section%2 == 0) {
        //return headerheight;
    }
    return 0;
}

Cette approche a également peu d'impact sur vos sources de données:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    int real_section = (int)indexPath.section / 2;
    //your code
}

En comparant avec d'autres approches, cette méthode est sûre sans changer le frame ou contentInsets de la tableview. J'espère que cela peut aider.

voie
la source
5

Le moyen le plus simple d'obtenir ce que vous voulez est de définir votre style de tableau comme UITableViewStyleGrouped, style de séparateur comme UITableViewCellSeparatorStyleNone:

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
    return CGFLOAT_MIN; // return 0.01f; would work same 
}

- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
    return [[UIView alloc] initWithFrame:CGRectZero];
}

N'essayez pas de retourner la vue du pied de page comme nil, n'oubliez pas de définir la hauteur de l'en-tête et la vue de l'en-tête, après avoir obtenu ce que vous souhaitez.

Michail Pidgorodetskiy
la source
4

Bien que cela ne résout pas votre problème, cela a été le cas pour moi lorsque je voulais faire une chose similaire. Au lieu de définir l'en-tête, j'ai utilisé le pied de page de la section ci-dessus. Ce qui m'a sauvé, c'est que cette section était petite et statique par nature, donc elle ne défilait jamais en dessous du bas de la vue.

Torbjörn
la source
Bonne idée. J'adore ce hack.
Steve Moser
Un peu drôle. apprécier l'idée, mais un hack est un hack. les en-têtes commenceraient à flotter en bas, donc ne résout pas vraiment le problème
Shyam Bhat
4

Pour Swift 3+

Utilisez simplement UITableViewStyleGroupedet réglez la hauteur du pied de page à zéro avec ce qui suit:

override func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
    return .leastNormalMagnitude
}
Tamás Sengel
la source
1
Vous pouvez renvoyer 0 au lieu de .leastNormalMagnitude. Vous devez également mettre en œuvretableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView?
Ilias Karim
@IliasKarim En le définissant sur 0, il a une hauteur non nulle. De plus, il n'est pas nécessaire d'implémenter la viewForFooterInSectionfonction dans ce cas.
Tamás Sengel le
0et a .leastNormalMagnitudeeu le même effet. La mise en œuvre de la viewForFooterSectionméthode est nécessaire. Vous devriez retourner nul. C'est sur Swift 5.1 avec Xcode 11.3.1.
Ilias Karim le
3

En réfléchissant à la manière d'aborder ce problème, je me suis souvenu d'un détail très important sur UITableViewStyleGrouped. La façon dont UITableView implémente le style groupé (les bordures arrondies autour des cellules) consiste à ajouter un backgroundView personnalisé à UITableViewCells, et non à UITableView. Chaque cellule est ajoutée un backgroundView en fonction de sa position dans la section (les lignes supérieures obtiennent la partie supérieure de la bordure de la section, celles du milieu la bordure latérale et celle du bas - enfin, la partie inférieure). Donc, si nous voulons juste un style simple et que nous n'avons pas de backgroundView personnalisé pour nos cellules (ce qui est le cas dans 90% des cas), alors tout ce que nous devons faire est d'utiliser UITableViewStyleGrouped et supprimer l'arrière-plan personnalisé . Cela peut être fait en suivant ces deux étapes:

Changez notre style tableView en UITableViewStyleGrouped Ajoutez la ligne suivante à cellForRow, juste avant de renvoyer la cellule:

cell.backgroundView = [[[UIView alloc] initWithFrame: cell.bounds] autorelease];

Et c'est tout. Le style tableView deviendra exactement comme UITableViewStylePlain, sauf pour les en-têtes flottants.

J'espère que cela t'aides!

James Laurenstin
la source
2

Peut-être que vous pourriez utiliser scrollViewDidScrollsur la tableView et modifier lecontentInset fonction de l'en-tête visible actuel.

Cela semble fonctionner pour mon cas d'utilisation!

extension ViewController : UIScrollViewDelegate{

    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        guard   let tableView = scrollView as? UITableView,
            let visible = tableView.indexPathsForVisibleRows,
            let first = visible.first else {
            return
        }

        let headerHeight = tableView.rectForHeader(inSection: first.section).size.height
        let offset =  max(min(0, -tableView.contentOffset.y), -headerHeight)
        self.tableView.contentInset = UIEdgeInsetsMake(offset, 0, -offset, 0)
   }
}
Martin
la source
1

Une autre façon de le faire est de créer une section vide juste avant celle sur laquelle vous voulez l'en-tête et de placer votre en-tête sur cette section. Parce que la section est vide, l'en-tête défilera immédiatement.

devguydavid
la source
1

Vous pouvez ajouter une section (avec zéro ligne) ci-dessus, puis définir la sectionFooterView ci-dessus comme headerView de la section actuelle, footerView ne flotte pas. J'espère que cela donne une aide.

Lee Lam
la source
Les FooterViews flottent, tout comme HeaderViews. Ils flottent simplement en bas de l'écran, pas en haut.
Mark A. Donohoe
0

Ignorez XAK. N'explorez aucune méthode privée si vous souhaitez que votre application ait une chance d'être acceptée par Apple.

C'est plus simple si vous utilisez Interface Builder. Vous ajouteriez un UIView en haut de la vue (où les images iront), puis ajouter votre tableview ci-dessous. IB devrait le dimensionner en conséquence; c'est-à-dire que le haut du tableau touche le bas de l'UIView que vous venez d'ajouter et sa hauteur couvre le reste de l'écran.

L'idée ici est que si cet UIView ne fait pas réellement partie de la vue de table, il ne défilera pas avec la vue de table. c'est à dire ignorer l'en-tête tableview.

Si vous n'utilisez pas le générateur d'interface, c'est un peu plus compliqué car vous devez obtenir le positionnement et la hauteur corrects pour la vue de la table.

imnk
la source
Cela ne répond pas à la question. Tricky fait référence au titleHeaderViews qui sont les vues qui se trouvent entre les cellules, pas à la vue d'en-tête du tableau, ce que vous semblez suggérer.
Daniel Wood
0

Vérifiez la réponse comment implémenter les en-têtes avec StoryBoard: Vues des en- têtes de table dans StoryBoards

Notez également que si vous ne mettez pas en œuvre

viewForHeaderInSection:(NSInteger)section

il ne flottera pas, ce qui est exactement ce que vous voulez.

Raphael Oliveira
la source
0

Pour supprimer complètement les sections d'en-tête de section flottante, vous pouvez le faire:

- (UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    return [[UIView alloc] init];
}

return nil ne fonctionne pas.

Pour désactiver le flottant tout en affichant les en-têtes de section, vous pouvez fournir une vue personnalisée avec ses propres comportements.

djskinner
la source
0

Une variante de la solution de @ samvermette:

/// Allows for disabling scrolling headers in plain-styled tableviews
extension UITableView {

    static let shouldScrollSectionHeadersDummyViewHeight = CGFloat(40)

    var shouldScrollSectionHeaders: Bool {
        set {
            if newValue {
                tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: bounds.size.width, height: UITableView.shouldScrollSectionHeadersDummyViewHeight))
                contentInset = UIEdgeInsets(top: -UITableView.shouldScrollSectionHeadersDummyViewHeight, left: 0, bottom: 0, right: 0)
            } else {
                tableHeaderView = nil
                contentInset = .zero
            }
        }

        get {
            return tableHeaderView != nil && contentInset.top == UITableView.shouldScrollSectionHeadersDummyViewHeight
        }
    }

}
raf
la source
0

L'extrait affiche un en-tête collant uniquement pour la première section. D'autres en-têtes de section flotteront avec des cellules.

func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {

    if section == 1 {
        tableView.contentInset = .zero
    }

}

func tableView(_ tableView: UITableView, didEndDisplayingHeaderView view: UIView, forSection section: Int) {
    if section == 0 {
        tableView.contentInset = .init(top: -tableView.sectionHeaderHeight, left: 0, bottom: 0, right: 0)
    }
}
Adobels
la source
-1

Cela peut être réalisé en affectant manuellement la vue d'en-tête dans la méthode viewDidLoad de UITableViewController au lieu d'utiliser les viewForHeaderInSection et heightForHeaderInSection du délégué. Par exemple, dans votre sous-classe de UITableViewController, vous pouvez faire quelque chose comme ceci:

- (void)viewDidLoad {
    [super viewDidLoad];

    UILabel *headerView = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 0, 40)];
    [headerView setBackgroundColor:[UIColor magentaColor]];
    [headerView setTextAlignment:NSTextAlignmentCenter];
    [headerView setText:@"Hello World"];
    [[self tableView] setTableHeaderView:headerView];
}

La vue d'en-tête disparaîtra alors lorsque l'utilisateur fera défiler. Je ne sais pas pourquoi cela fonctionne comme ça, mais cela semble réaliser ce que vous cherchez à faire.

Johnny Oshika
la source
Ce n'est pas pour une section, c'est pour 1 en-tête en haut.
makdad
-1

Peut-être que vous pouvez simplement rendre l'arrière-plan de la vue d'en-tête transparent:

- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section {
    view.tintColor = [UIColor clearColor];
}

Ou appliquez-le globalement:

    [UITableViewHeaderFooterView appearance].tintColor = [UIColor clearColor];
Tinpont
la source
-2

J'ai une autre solution encore plus simple, à utiliser sans mise en page automatique et avec tout ce qui est fait via le XIB:

1 / Mettez votre en-tête dans la vue du tableau par glisser-déposer directement sur la vue du tableau.

2 / Dans l'inspecteur de taille de l'en-tête nouvellement créé, changez simplement son autosizing: vous ne devez laisser que les ancres du haut, gauche et droite, plus le remplissage horizontalement.

Voilà comment il doit être défini pour l'en-tête

Cela devrait faire l'affaire !

CyberDandy
la source
-2

Selon la réponse de @ samvermette, j'ai implémenté le code ci-dessus dans Swift pour faciliter l'utilisation de Swift par les codeurs.

let dummyViewHeight = CGFloat(40)
self.tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: self.tableView.bounds.size.width, height: dummyViewHeight))
self.tableView.contentInset = UIEdgeInsetsMake(-dummyViewHeight, 0, 0, 0)
Bingerz
la source
-2

réf: https://stackoverflow.com/a/26306212

let tableView = UITableView(frame: .zero, style: .grouped)

PLUSE

func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    if section == 0 {
        return 40
    }else{
        tableView.sectionHeaderHeight = 0
    }

    return 0
}

Cela a aidé à utiliser l'espace d'en-tête

Pratik
la source
S'il vous plaît, ne faites pas ça🙏
MQoder
-3

Dernière mise à jour 2020

Testé avec Xcode 14.

Pour masquer un en-tête de section, renvoyez nil pour le titre du délégué de section

func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    return nil
}
Saranjith
la source
-4

vous pouvez facilement y parvenir en implémentant la méthode viewForHeaderInSection dans la classe de délégué tableview. cette méthode attend un UIView comme objet de retour (qui est votre vue d'en-tête). j'ai fait la même chose dans mon code

Raj
la source
L'affiche originale ne veut pas d'en-tête personnalisé. Ils veulent un en-tête qui ne «flotte» pas en haut du tableau. Votre suggestion flotte toujours.
jemmons
changez la tableview en UITableViewStyleGrouped avec viewforheader, puis il s'arrêtera
mskw