207 votes

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

J'utilise un UITableView pour mettre en page le contenu des "pages". J'utilise les en-têtes de la vue tableau pour mettre en page certaines images, etc. et je préférerais qu'ils ne flottent pas, mais restent statiques, comme c'est le cas lorsque le style est défini comme suit UITableViewStyleGrouped .

Autre que l'utilisation UITableViewStyleGrouped existe-t-il un moyen de le faire ? J'aimerais éviter d'utiliser l'option groupée, car elle ajoute une marge à toutes mes cellules et nécessite la désactivation de l'affichage en arrière-plan pour chacune des cellules. J'aimerais avoir le contrôle total de ma mise en page. L'idéal serait une "UITableViewStyleBareBones", mais je n'ai pas vu cette option dans la documentation...

Merci beaucoup,

1 votes

63 votes

Utiliser le style de table UITableViewStyleGrouped - voici la réponse pour tous ceux qui cherchent à désactiver les en-têtes flottants et ne lisent pas toute la question (cela m'est arrivé...).

0 votes

@Kasztan C'est une solution de ligne zéro qui fonctionne très bien ! Merci.

364voto

samvermette Points 20225

Un moyen probablement plus facile d'y parvenir :

Objective-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);

Swift :

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 = UIEdgeInsets(top: -dummyViewHeight, left: 0, bottom: 0, right: 0)

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

5 votes

Cela fonctionne comme un charme !!! La présence d'un en-tête de table empêche les en-têtes de section de flotter. Et un en-tête invisible avec des inserts de contenu appropriés pour la table fait l'affaire Merci beaucoup ! Je me demande pourquoi cette réponse ne suscite pas beaucoup d'attention

4 votes

Je ne le crois toujours pas ! Pas d'API privées, pas de fouille dans les classes, rien ! J'ai été confronté à ce problème depuis des années et j'ai ajouté des tableviews au-dessus des scroll views (avec le scroll de tableview désactivé), ce qui faisait défiler les en-têtes de table normalement. mais je viens de commencer à chercher si apple a fourni de nouvelles méthodes récemment pour résoudre ce problème donc je suis heureux d'être tombé sur votre réponse. merci encore

0 votes

Vous avez sauvé ma journée avec cette petite chose. Il fonctionne comme prévu sans une seule ligne de code. Je suis stupéfait. Merci Monsieur !

295voto

david72 Points 41

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

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

77voto

AVERTISSEMENT Cette solution met en œuvre une méthode API réservée. Cela pourrait empêcher l'application d'être approuvée par Apple pour la distribution sur l'AppStore.

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

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

- (BOOL)allowsHeaderViewsToFloat;
- (BOOL)allowsFooterViewsToFloat;

36voto

HannahCarney Points 3108

Dans le Générateur d'interface, cliquez sur la vue Tableau de votre problème.

problem table view

Ensuite, allez dans l'inspecteur des attributs et changez le style Plain en groupé. ;) Facile

easy

28voto

Leo Olympian Points 214

Ok, je sais qu'il est tard mais je devais le faire. J'ai passé 10 heures à chercher une solution fonctionnelle mais je n'ai pas trouvé de réponse complète. J'ai trouvé quelques conseils mais difficiles à comprendre pour les débutants. J'ai donc dû mettre mon grain de sel et compléter la réponse.

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

Donc, les étapes sont.

  1. Implémente 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 les délégués standards ).

    - (NSString *)tableView: (UITableView *)tableView titleForHeaderInSection:(NSInteger)section
    {
        NSString *headerTitle = [sectionArray objectAtIndex:section];
        return headerTitle;
    }
  3. Implémentez 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. Renvoyer 0.0f en 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érifie si(indexpath.row == 0) et renvoie la hauteur de cellule souhaitée pour l'en-tête de section, sinon renvoie 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 none. ELSE implémentez la cellule comme vous voulez que la cellule normale soit.

    - (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. Implémentez maintenant willSelectRowAtIndexPath et renvoyez nil si indexpath.row == 0. Cela permettra d'éviter que didSelectRowAtIndexPath ne soit déclenché pour la ligne d'en-tête de section.

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

    - (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.

1 votes

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.

0 votes

En fait, je plie + déplie les rangées lorsque l'en-tête est sélectionné. Mais il est bon de savoir que vous pouvez le faire

0 votes

Excellente réponse, mais pourquoi la vérification "if (indexPath.row != 0)" dans "didSelectRowAtIndexPath" ? S'agit-il simplement d'une sécurité supplémentaire ? Le rang ne peut jamais être égal à 0 avec l'implémentation de 'willSelectRowAtIndexPath', n'est-ce pas ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X