dimanche 29 janvier 2012

Voir la table Multi-Mode Edition Row


Si vous avez joué autour du tout avec UITableView de "Edit Mode", vous avez probablement été déçu qu'il ne supporte pas la possibilité de sélectionner puis supprimer plusieurs lignes dans la table, la façon dont vous pouvez faire dans l'application Mail d'Apple . Il a été l'une des améliorations les bienvenus faite dans l'iPhone OS 2.0, et j'ai été un peu déçu quand j'ai découvert que la capacité de faire qui n'a pas été ajouté à UITableView avec la version 2.0.

Personnellement, j'aimerais voir la fonctionnalité dans les applications iPhone plus basée sur des tables, donc j'ai jeté ensemble un projet petit échantillon iPhone qui montre comment le faire. Vous pouvez trouver le projet Right Here.

Je ne vais pas à marcher à travers les projets entiers, comme la plupart des applications standards, il est des capacités, mais je tenais à souligner l'approche générale que j'ai utilisé. Je ne sais pas si c'est exactement ce courrier qu'il fait, et je ne suis certainement pas sûr que ce soit la meilleure façon de le faire, mais ça fonctionne. Le seul aspect de la mise en œuvre Mail Je n'ai pas change la couleur de fond des lignes sélectionnées en mode édition. Je l'ai essayé, mais devenait un comportement bizarre où la dernière ligne sélectionnés a été de retour en arrière vers le blanc, mais quand une autre ligne a été ajoutée à la sélection, alors il serait revenir à la couleur correcte. À un certain moment, je vais plonger et essayer de comprendre ce qui n'allait pas avec ce code, mais pour le moment, cela devrait fonctionner assez bien pour vous et pour au moins vous donner une idée de comment le processus peut fonctionner.

Dans ma classe contrôleur, j'ai défini quelques constantes et des macros:

#define kCellImageViewTag 1000
#define kCellLabelTag 1001

#define kLabelIndentedRect CGRectMake(40.0, 12.0, 275.0, 20.0)
#define kLabelRect CGRectMake(15.0, 12.0, 275.0, 20.0)

Les deux premiers seront utilisés plus tard pour récupérer les sous-vues correct de la cellule de tableau. Les deux derniers de définir les positions possibles du texte de la ligne. Si nous sommes en mode édition, le texte va être déplacé sur un peu (ce qui sera animé). En définissant les deux rectangles ici, nous pouvons changer le texte plus facilement simplement en assignant une nouvelle valeur à la propriété frame du label.

Dans mon contrôleur, j'ai deux tableaux mutables. On va contenir les valeurs d'affichage, l'autre sera utilisée pour maintenir les lignes qui sont sélectionnées quand nous sommes en mode édition. J'ai également définir un booléen qui va déterminer le moment où nous sommes en mode édition. Je n'appelle pas le modifier en mode parce que je ne veux pas risquer un conflit de nom ou de la confusion avec le code d'Apple.

NSMutableArray *countries;
NSMutableArray *selectedArray;
BOOL inPseudoEditMode;

J'ai également deux pointeurs UIImage qui contiennent l'image cochée ou décochée. C'est un peu klugey - le non contrôlée est juste un cercle, donc je devrais probablement avoir simplement utilisé CoreGraphics pour dessiner le cercle, mais ce fut plus facile.

UIImage *selectedImage;
UIImage *unselectedImage;

J'ai créé une méthode qui va créer le selectedArray, il peupler avec des objets NSNumber qui détiennent une valeur NO pour chaque ligne. Ce me permet facilement réinitialiser la sélection après une suppression.

- (void)populateSelectedArray
{
NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:[countries count]];
for (int i=0; i [array addObject:[NSNumber numberWithBool:NO]];
self.selectedArray = array;
[array release];
}

Cette méthode est appelée dans le viewDidLoad, et aussi chaque fois que nous supprimer des lignes. La méthode viewDidLoad embarque également un tableau avec des chaînes tiré à partir d'un fichier texte et les charges des deux UIImages.

Il ya une méthode IBAction pour passer en mode édition. Cette est appelée lorsque l'utilisateur appuie sur le bouton "Supprimer" dans la barre de navigation. Il change la valeur de inPsuedoEditMode et aussi des peaux ou Révèle la barre d'outils en bas, qui a le bouton "Supprimer" qui provoque les lignes sélectionnées pour obtenir supprimé.

-(IBAction)togglePseudoEditMode
{
self.inPseudoEditMode = !inPseudoEditMode;
toolbar.hidden = !inPseudoEditMode;

[self.tableView reloadData];
}


La plupart des travaux est ici dans le tableView: cellForRowAtIndexPath: méthode. C'est là que nous devons examiner si nous sommes en mode édition, et si nous sommes en mode édition, regardez les lignes qui sont sélectionnées.


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *EditCellIdentifier = @" editcell";


UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:EditCellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:EditCellIdentifier] autorelease];


UILabel *label = [[UILabel alloc] initWithFrame:kLabelRect];
label.tag = kCellLabelTag;
[cell.contentView addSubview:label];
[label release];

UIImageView *imageView = [[UIImageView alloc] initWithImage:unselectedImage];
imageView.frame = CGRectMake(5.0, 10.0, 23.0, 23.0);
[cell.contentView addSubview:imageView];
imageView.hidden = !inPseudoEditMode;
imageView.tag = kCellImageViewTag;
[imageView release];

}

[UIView beginAnimations:@"cell shift" context:nil];

UILabel *label = (UILabel *)[cell.contentView viewWithTag:kCellLabelTag];
label.text = [countries objectAtIndex:[indexPath row]];
label.frame = (inPseudoEditMode) ? kLabelIndentedRect : kLabelRect;

UIImageView *imageView = (UIImageView *)[cell.contentView viewWithTag:kCellImageViewTag];
NSNumber *selected = [selectedArray objectAtIndex:[indexPath row]];
imageView.image = ([selected boolValue]) ? selectedImage : unselectedImage;
imageView.hidden = !inPseudoEditMode;
[UIView commitAnimations];

return cell;
}

Avis quelques choses

  • nous créer manuellement les sous-vues pour afficher le contenu de la cellule de tableau, et nous leur assignons balises. Les balises nous permettent de récupérer les sous-vue correcte quand nous arriverons dequeued cellules au lieu de créer un nouveau.

  • Nous appelons beginAnimations: forContext: et commitAnimations: autour de nos modifications afin que les changements s'animent pour nous. C'est tout ce que nous avons à faire pour faire tourner le mode édition sur et en dehors d'animation


Quand une ligne est touché, et nous sommes en mode édition, nous avons à définir la ligne correspondante dans le tableau de sélection pour OUI si c'est actuellement le NO et vice versa.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
if (inPseudoEditMode)
{
BOOL selected = [[selectedArray objectAtIndex:[indexPath row]] boolValue];
[selectedArray replaceObjectAtIndex:[indexPath row] withObject:[NSNumber numberWithBool:!selected]];
[self.tableView reloadData];
}
}

Il ya une autre méthode que la clé de ce processus, qui est une autre méthode d'action qui est appelée lorsque le bouton Supprimer dans la barre d'outils devient pressé. Parce que cette barre d'outils est affichée uniquement lorsque nous sommes en mode édition, nous n'avons pas de vérifier que, nous venons de faire le supprimer. Parce que vous ne pouvez pas supprimer des objets d'une collection tout en énumérant sur eux, cette méthode est un peu plus complexe que vous pourriez vous attendre.

-(IBAction)doDelete
{
NSMutableArray *rowsToBeDeleted = [[NSMutableArray alloc] init];
NSMutableArray *indexPaths = [[NSMutableArray alloc] init];
int index = 0;
for (NSNumber *rowSelected in selectedArray)
{
if ([rowSelected boolValue])
{

[rowsToBeDeleted addObject:[countries objectAtIndex:index]];
NSUInteger pathSource[2] = {0, index};
NSIndexPath *path = [NSIndexPath indexPathWithIndexes:pathSource length:2];
[indexPaths addObject:path];
}
index++;
}

for (id value in rowsToBeDeleted)
{
[countries removeObject:value];
}

[self.tableView deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade];

[indexPaths release];
[rowsToBeDeleted release];
inPseudoEditMode = NO;
[self populateSelectedArray];
[self.tableView reloadData];
}

Quoi qu'il en soit, j'espère que cela est utile pour certaines personnes. Si vous avez des questions, mettez-les dans les commentaires, ou envoyez-moi un e-mail.

Aucun commentaire: