web-dev-qa-db-fra.com

Combinaison de contenu statique et de prototype dans une vue de tableau

Existe-t-il un moyen de combiner des cellules tableview statiques (contenu statique) avec des cellules tableview dynamiques (contenu prototype) à l'aide d'un storyboard?

36
tazboy

Je suggère que vous traitiez votre table comme dynamique, mais incluez les cellules que vous voulez toujours au sommet. Dans le Storyboard, placez une UITableViewController et faites-la utiliser un tableau dynamique. Ajoutez autant de prototypes UITableViewCell que nécessaire à la table. Disons, un pour vos cellules statiques et un pour représenter les cellules variables.

Dans votre classe UITableViewDataSource:

#define NUMBER_OF_STATIC_CELLS  3

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [self.dynamicModel count] + NUMBER_OF_STATIC_CELLS;
}

et alors

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    if (indexPath.row < NUMBER_OF_STATIC_CELLS) {
        // dequeue and configure my static cell for indexPath.row
        NSString *cellIdentifier = ... // id for one of my static cells
    } else {
        // normal dynamic logic here
        NSString *cellIdentifier = @"DynamicCellID"
        // dequeue and configure for [self.myDynamicModel objectAtIndex:indexPath.row]
    }
}
55
danh

J'ai eu un problème, bien que ce soit une légère variante de cela. En fait, je voulais mélanger des cellules dynamiques et statiques, mais dans des groupes différents. Ce qui signifie que le groupe 1 aurait uniquement des cellules statiques et que le groupe 2 aurait des cellules dynamiques. 

Pour ce faire, j'ai codé en dur les valeurs des cellules statiques (en fonction de leurs identificateurs de cellules prototypes). Les sections dynamiques auraient un contenu normal rempli dynamiquement. Voici un exemple de code dans le cas où quelqu'un d'autre aurait le même problème:

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{    
    if (section == 1){
        return @"Dynamic Cells";
    }
    if (section == 0){
        return @"Static Cells";
    }
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    if (section == 0) {
        return 1; //However many static cells you want
    } else {
        return [_yourArray count];
    }
}

-(UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
    if (indexPath.section == 0) {
        NSString *cellIdentifier = @"staticCellType";   
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

        if (cell == nil) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
        }

        cell.textLabel.text = @"some static content";        
        return cell;

    } else if (indexPath.section == 1){

        NSString *cellIdentifier = @"dynamicCellType";
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

        if (cell == nil) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
        }

        cell.textLabel.text = [_yourArray objectAtIndex:indexPath.row];
        return cell;

    } 
    return nil;

}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 2;
}
12
AbuZubair

Étant donné que personne n’a réellement apporté de réponse réelle au problème (en utilisant à la fois des cellules statiques et des cellules prototypes dans la même vue de tableau), j’ai pensé que j’allais laisser tomber . Cela peut être fait!

Créez vos cellules statiques comme bon vous semble. Pour les sections nécessitant une cellule dynamique, si vous n'utilisez PAS le type UITableViewCell standard, vous devez créer votre cellule personnalisée dans un Nib séparé, sinon vous pouvez utiliser les types standard. Ensuite, implémentez les délégués suivants. En gros, pour chacun de ces délégués, pour les choses statiques que nous voulons appeler super, pour la dynamique, nous retournons nos valeurs.

Tout d’abord, SI vous devez afficher de manière sélective votre section dynamique, vous voudrez implémenter le numberOfSectionsInTableView (sinon, vous pouvez laisser ce délégué à l’extérieur):

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    int staticSections = 1;
    int dynamicSections = 1;
    if (SOME_BOOLEAN) {
        return staticSections + dynamicSections;
    } else {
        return staticSections;
    }
}

Ensuite, vous devez implémenter numberOfRowsInSection:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    if (section == 1) {
        return A_COUNT;
    } else {
        return [super tableView:tableView numberOfRowsInSection:section];
    }
}

Ensuite, vous devez implémenter heightForRowAtIndexPath:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.section == 1) {
        return 44.0f;
    } else {
        return [super tableView:tableView heightForRowAtIndexPath:indexPath];
    }
}

Puis indentationLevelForRowAtIndexPath:

- (NSInteger)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.section == 1) {
        return 1; // or manually set in IB (Storyboard)
    } else {
        return [super tableView:tableView indentationLevelForRowAtIndexPath:indexPath]; // or 0
    }
}

Enfin, cellForRowAtIndexPath:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.section == 1) {
        SomeObject *obj = self.someArray[indexPath.row];
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"DynamicCell" forIndexPath:indexPath];
        cell.textLabel.text = obj.textValue;
        return cell;
    } else {
        return [super tableView:tableView cellForRowAtIndexPath:indexPath];
    }
}
5
Sean

Vous pouvez toujours faire en sorte que vos vues de table ressemblent à la table statique mais le définir dans le code. Définissez les sections, le montant ou les lignes par section, les en-têtes, etc. via les méthodes de délégation. 

3
Michael

Malheureusement, cela n’est pas possible car les vues de table statique doivent se trouvent dans un UITableViewController et n’autorisent qu’une seule vue de table.

Ce que vous devez faire est de créer trois UITableviewCell plus dynamiques et de les charger individuellement pour les trois premières lignes contenant le contenu statique.

Si vous ne savez pas comment faire cela, faites-le moi savoir et je pourrai trouver du code.

3
lnafziger

Vous ne pouvez pas avoir une table statique et l'autre dynamique dans le même contrôleur de vue, vous devrez donc les rendre toutes les deux dynamiques. Dans la première vue de table, vous configurerez les cellules dans le code lors de l'initialisation du contrôleur de vue, ne les mettez jamais à jour.

  1. Ajoutez un UIViewController à votre story-board. 
  2. Ajoutez deux vues de table (Not TableViewControllers) au contrôleur UIView.
  3. Sélectionnez chaque tableView et configurez les deux pour les cellules dynamiques. 
  4. Construisez et attachez votre contrôleur de vue. 2 tableview sur une seule vue explique cette étape.

Une autre option consiste à incorporer votre vue table dynamique dans une vue similaire au lien décrit à l'étape 4, puis à faire ce que vous souhaitiez dans le reste de la vue pour configurer ce que vous aviez prévu de faire avec des cellules statiques. en utilisant des vues de défilement, des étiquettes et des boutons.

2
T.J.

Une façon d'avoir du contenu dynamique dans une vue de table statique consiste à cloner des cellules lorsque des lignes supplémentaires sont nécessaires.

Pour la section dynamique de ma vue tableau, je dispose une ou plusieurs cellules dans Interface Builder. Au moment de l'exécution, je peux les cloner en les archivant à l'aide de NSCoder, puis en les désarchivant.

Cela fonctionne, mais n’est pas nécessairement plus joli que de commencer par une vue de table prototype dynamique et de créer des lignes statiques à partir de là.

Il échoue avec les cellules de vue de tableau standard. Les étiquettes de texte créées tardivement ne sont pas correctement présentées. J'ai donc utilisé les sous-classes UITableViewCell où je m'occupe de l'archivage et de la désarchivage des sous-vues.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.section == kContactsSection) {
        NSArray     *contacts   = self.contacts;
        Contact     *contact    = [contacts objectAtIndex:indexPath.row];
        NSString    *name       = contact.name;
        NSString    *role       = contact.role;

        if ([role length] == 0) {
            NNContactDefaultTableViewCell *cell = (id)[tableView dequeueReusableCellWithIdentifier : @"contactDefault"];

            if (cell == nil) {
                NNContactDefaultTableViewCell   *template   = (id)[super tableView : tableView
                                                         cellForRowAtIndexPath :[NSIndexPath indexPathForRow:0 inSection:kContactsSection]];

                NSData                          *data       = [NSKeyedArchiver archivedDataWithRootObject:template];

                cell = [NSKeyedUnarchiver unarchiveObjectWithData:data];
            }

            cell.contactTextLabel.text = name;

            return cell;
        }
        else {
            NNContactDetailTableViewCell *cell = (id)[tableView dequeueReusableCellWithIdentifier : @"contactDetail"];

            if (cell == nil) {
                NNContactDetailTableViewCell    *template   = (id)[super tableView : tableView
                                                        cellForRowAtIndexPath :[NSIndexPath indexPathForRow:1 inSection:kContactsSection]];

                NSData                          *data       = [NSKeyedArchiver archivedDataWithRootObject:template];

                cell = [NSKeyedUnarchiver unarchiveObjectWithData:data];
            }

            cell.contactTextLabel.text          = name;
            cell.contactDetailTextLabel.text    = role;

            return cell;
        }
    }

    return [super tableView:tableView cellForRowAtIndexPath:indexPath];
}

Dans l'exemple ci-dessus, j'ai deux types de cellules. Les deux sont présentés dans Interface Builder dans le cadre d'une vue de table statique.

Pour obtenir du contenu dynamique dans une section, je dois également remplacer les méthodes suivantes:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    if (section == kContactsSection) {
        NSArray     *contacts       = self.contacts;
        NSUInteger  contactCount    = [contacts count];

        return contactCount;
    }

    return [super tableView:tableView numberOfRowsInSection:section];
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSInteger   section = indexPath.section;
    NSInteger   row     = indexPath.row;

    if (section == kContactsSection) {
        return [super tableView:tableView heightForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:kContactsSection]];
    }

    return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}

- (CGFloat)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSInteger   section     = indexPath.section;

    if (section == kContactsSection) {
        CGFloat indentation = [super tableView:tableView indentationLevelForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:kContactsSection]];

        return indentation;
    }

    CGFloat     indentation = [super tableView:tableView indentationLevelForRowAtIndexPath:indexPath];

    return indentation;
}
0
Pierre Bernard

Vous pouvez également créer des boutons (un pour chaque cellule statique que vous avez) qui sont stylés comme vos cellules et les placer dans la tableHeaderView ou la tableFooterView de la UITableView; ces boutons ne sont que des vues après tout.

Vous devrez ajouter une certaine logique pour effectuer des sélections sur les boutons par rapport aux cellules afin de conserver l'aspect et la convivialité habituels.

Bien entendu, cela suppose que vous souhaitiez insérer des cellules statiques dans la vue tableau en haut ou en bas du tableau.

0
BeckProduct