web-dev-qa-db-fra.com

Modifier le comportement de défilement par défaut de l'en-tête de section UITableView

J'ai un UITableView avec deux sections. C'est une simple vue de table. J'utilise viewForHeaderInSection pour créer des vues personnalisées pour ces en-têtes. Jusqu'ici tout va bien.

Le comportement de défilement par défaut est que, lorsqu'une section est rencontrée, l'en-tête de la section reste ancré sous la barre de navigation, jusqu'à ce que la section suivante apparaisse dans la vue.

Ma question est la suivante: puis-je modifier le comportement par défaut pour que les en-têtes de section NE restent PAS ancrés en haut, mais plutôt que de faire défiler la barre de navigation sous le reste des lignes de la section?

Est-ce que je manque quelque chose d'évident?

Merci.

145
davidjhinson

La façon dont j'ai résolu ce problème est d'ajuster le contentOffset en fonction du contentInset dans le UITableViewControllerDelegate (s'étend UIScrollViewDelegate) comme suit:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
       CGFloat sectionHeaderHeight = 40;
   if (scrollView.contentOffset.y<=sectionHeaderHeight&&scrollView.contentOffset.y>=0) {
       scrollView.contentInset = UIEdgeInsetsMake(-scrollView.contentOffset.y, 0, 0, 0);
   } else if (scrollView.contentOffset.y>=sectionHeaderHeight) {
       scrollView.contentInset = UIEdgeInsetsMake(-sectionHeaderHeight, 0, 0, 0);
   }
}

Le seul problème ici est qu’il perd un peu de rebond lors du défilement vers le haut.


{REMARQUE: Le "40" doit correspondre à la hauteur exacte de VOTRE en-tête de section 0. Si vous utilisez un nombre plus grand que la hauteur de votre en-tête de section 0, vous verrez que le toucher du doigt est affecté (essayez comme "1000" et vous verrez que le comportement de rebond est un peu bizarre en haut). Si le nombre correspond à la hauteur de l'en-tête de votre section 0, la sensation au doigt semble être parfaite ou presque parfaite.}

173
awulf

Vous pouvez également ajouter une section avec zéro ligne en haut et utiliser simplement le pied de page de la section précédente comme en-tête pour la suivante.

86
voidStern

Si c’était ce que je faisais, je tirerais profit du fait que UITableViews dans le style Plain contient des en-têtes collants et que ceux du style Grouped n’en ont pas. J'essaierais probablement au moins d'utiliser une cellule de tableau personnalisée pour imiter l'apparence des cellules simples dans une table groupée.

Je n'ai pas vraiment essayé cela, donc ça ne marchera peut-être pas, mais c'est ce que je suggère de faire.

35
Colin Barrett

Je sais que ça vient tard, mais j'ai trouvé la solution définitive!

Si vous avez 10 sections, laissez la source de données en renvoyer 20. Utilisez des nombres pairs pour les en-têtes de section et des nombres impairs pour le contenu de la section. quelque chose comme ça

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    if (section%2 == 0) {
        return 0;
    }else {
        return 5;
    }
}

-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    if (section%2 == 0) {
        return [NSString stringWithFormat:@"%i", section+1];
    }else {
        return nil;
    }
}

Voila! :RÉ

28
LocoMike

Il y a plusieurs choses à faire pour résoudre ce problème d'une manière non-hacky:

  1. Définissez le style d'affichage de la table sur UITableViewStyleGrouped
  2. Définissez la vue sous forme de tableau backgroundColor sur [UIColor clearColor]
  3. Définissez backgroundView sur chaque cellule de la vue tableau en vue vide avec backgroundColor [UIColor clearColor]
  4. Si nécessaire, définissez la vue de table rowHeight de manière appropriée ou remplacez tableView:heightForRowAtIndexPath: si les rangées individuelles ont des hauteurs différentes.
15
Neil Gall

Initialement posté Ici , une solution rapide utilisant l’IB. La même chose peut être faite par programmation bien que tout simplement.

Un moyen probablement plus facile d'y parvenir (en utilisant IB):

Faites glisser un UIView sur votre TableView pour en faire sa vue d’en-tête.

  1. Définissez la hauteur de vue d'en-tête à 100px
  2. Définissez la tableview contentInset (haut) sur -100
  3. Les en-têtes de section défileront maintenant comme une cellule ordinaire.

Certaines personnes ont commenté en disant que cette solution cache le premier en-tête, mais je n'ai pas remarqué un tel problème. Cela fonctionnait parfaitement pour moi et était de loin la solution la plus simple que j'ai vue jusqu'à présent.

15
Doc

Je n’étais pas satisfait des solutions décrites ici jusqu’à présent, j’ai donc essayé de les combiner. Le résultat est le code suivant, inspiré par @awulf et @cescofry. Cela fonctionne pour moi parce que je n'ai pas d'en-tête de vue tableau réel. Si vous avez déjà un en-tête de vue de tableau, vous devrez peut-être ajuster la hauteur.

// Set the Edge inset
self.tableView.contentInset = UIEdgeInsetsMake(-23.0f, 0, 0, 0);

// Add a transparent UIView with the height of the section header (ARC enabled)
[self.tableView setTableHeaderView:[[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 100.0f, 23.0f)]];
14
Thomas Kekeisen

Il suffit de changer le style de TableView:

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

Documentation UITableViewStyle :

UITableViewStylePlain - Une vue de table simple. Tous les en-têtes de section ou les pieds de page sont affichés sous forme de séparateurs en ligne et flottants lorsque la vue tabulaire défile.

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

14
Arthur S

Select Grouped TableView style

Sélectionnez le style d'affichage de la table groupée dans l'inspecteur d'attributs de votre tableView dans le storyboard.

6
Arjun Shukla

Changez votre style TableView:

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

Selon la Apple pour UITableView:

UITableViewStylePlain - Une vue de table simple. Tous les en-têtes de section ou les pieds de page sont affichés sous forme de séparateurs en ligne et flottants lorsque la vue tabulaire défile.

UITableViewStyleGrouped: une vue de tableau dont les sections présentent des groupes distincts de lignes. Les en-têtes et les pieds de section ne flottent pas. J'espère que ce petit changement vous aidera.

5
Aks

J'ai trouvé une solution alternative, utilisez la première cellule de chaque section à la place d'une vraie section d'en-tête. Cette solution ne semble pas si nette, mais fonctionne si bien, vous pouvez utiliser une cellule prototype définie pour votre section d'en-tête, et dans la méthode - cellForRowAtIndexPath demandez l'indexPath.row == 0, si la valeur est true, utilisez la cellule prototype de la section d'en-tête, sinon utilisez votre cellule prototype par défaut.

4
AlexBB

Définissez l'en-têteView de la table avec une vue transparente avec la même hauteur que l'en-tête en vue en coupe. Également initialiser la table avec un y-frame à -height.

self.tableview = [[UITableView alloc] initWithFrame:CGRectMake(0, - height, 300, 400)];

UIView *headerView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, width, height)] autorelease];
[self.tableView setTableHeaderView:headerView];
4
cescofry

Maintenant que le style groupé est fondamentalement identique au style brut dans iOS 7 (en termes de planéité et d’arrière-plan), pour nous, le correctif le plus simple et le plus simple (le moins hacky) consistait simplement à modifier le style de la vue de table en groupé. Jacking avec contentInsets a toujours été un problème lorsque nous avons intégré une barre de navigation à défilement en haut. Avec un style de vue groupée, il a exactement la même apparence (avec nos cellules) et les en-têtes de section restent fixes. Pas d'étrangeté de défilement.

2
Greg Combs

Assignez un encart négatif à votre tableView. Si vous avez des en-têtes de section haute de 22 pixels et que vous ne voulez pas qu'ils soient collants, juste après reloadData, ajoutez:

self.tableView.contentInset = UIEdgeInsetsMake(-22, 0, 0, 0); 
self.tableView.contentSize = CGSizeMake(self.tableView.contentSize.width, self.tableView.contentSize.height+22); 

Fonctionne comme un charme pour moi. Fonctionne également pour les pieds de section, assignez simplement l’encart négatif en bas.

1
Mike A

Vérifiez ma réponse ici . C'est le moyen le plus simple d'implémenter les en-têtes de section non flottante sans aucun piratage.

0
Sumit Anantwar

J'ajoute le tableau à une vue de défilement et cela semble bien fonctionner.

0
Dolbex

Version rapide de @awulf answer, qui fonctionne très bien!

func scrollViewDidScroll(scrollView: UIScrollView) {
    let sectionHeight: CGFloat = 80
    if scrollView.contentOffset.y <= sectionHeight {
        scrollView.contentInset = UIEdgeInsetsMake( -scrollView.contentOffset.y, 0, 0, 0)
    }else if scrollView.contentOffset.y >= sectionHeight {
        scrollView.contentInset = UIEdgeInsetsMake(-sectionHeight, 0, 0, 0)
    }
}
0
Jeff

La réponse de @ LocoMike convenait le mieux à ma tableView, mais elle se cassait également lorsque l'on utilisait des bas de page. Voici donc la solution corrigée lors de l’utilisation des en-têtes et des pieds de page:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return (self.sections.count + 1) * 3;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    if (section % 3 != 1) {
        return 0;
    }
    section = section / 3;
    ...
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
    if (section % 3 != 0) {
        return nil;
    }
    section = section / 3;
    ...
}

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

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
    if (section % 3 != 2) {
        return 0;
    }
    section = section / 3;
    ...
}

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

- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
    if (section % 3 != 2) {
        return nil;
    }
    section = section / 3;
    ...
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    int section = indexPath.section;
    section = section / 3;
    ...
}
0
marmor

Changez votre style TableView:

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

Selon la Apple pour UITableView:

UITableViewStylePlain- A plain table view. Any section headers or footers are displayed as inline separators and float when the table view is scrolled.

UITableViewStyleGrouped- A table view whose sections present distinct groups of rows. The section headers and footers do not float.
Hope this small change will help you ..
0
Aks