UITableView mise en évidence des cellules sélectionnées

Bonjour,

J'utilise une UITableView avec multi-sélection, et j'essaye de modifier l'aspect des cellules sélectionnées. Par défaut, les cellules deviennent bleues, et je préfèrerais qu'elle soient "cochées".

Ne trouvant pas, j'ai fait ce code :
<br />
-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {<br />
	[tableView deselectRowAtIndexPath:indexPath animated:NO];<br />
	UITableViewCell *cell=[myTable cellForRowAtIndexPath:indexPath];<br />
	if (cell.accessoryType==UITableViewCellAccessoryNone) {<br />
		cell.accessoryType=UITableViewCellAccessoryCheckmark;  <br />
	} else {<br />
		cell.accessoryType=UITableViewCellAccessoryNone;<br />
	}<br />
}<br />




Donc, je désélectionne mes cellules au fur et à  mesure qu'elles sont sélectionnées, et je modifie l'accessoryType. çà  fonctionne, mais çà  ne me plais pas trop comme solution, je trouve que çà  n'est pas très propre, et je pense qu'il doit exister une solution plus simple, d'autant que pour savoir quelle sont les cellules sélectionnées, je doit tester l'accessoryType...

J'ai cherché si l'on pouvait choisir l'aspect des cellules sélectionnées, mais je n'ai pas trouvé. Quelqu'un aurait-il une piste ?



Merci d'avance

Réponses

  • Hello Alf,



    En effet ce n'est pas très joli tout ça image/smile.png' class='bbc_emoticon' alt=':)' />

    Je n'ai jamais réalisé de sélection multiple mais un petit tout dans la doc Apple me donne des indices quant à  l'implémentation de ton idée.

    En étape ça fait :
    • Classe fille de UITableViewCell tu déclareras
    • UITableViewCellEditingStyleNone à  son attribut selectionStyle tu donneras
    • UIView de selection tu créeras (avec ta foutu croix)
    • L'ensemble à  l'attribut multipleSelectionBackgroundView tu ajouteras
    • De l'argent sur mon compte tu me verseras.


    Voilà  ^^

    Bon si ça se trouve je me suis planté image/smile.png' class='bbc_emoticon' alt=':)' />
  • AliGatorAliGator Membre, Modérateur
    En effet ce n'est pas du tout comme cela qu'il faut faire.

    N'oublie pas le MVC. Et n'oublie surtout pas que les cellules d'une UITableView sont recyclées quand tu scrolles. Du coup avec ton système ça risque d'être du grand n'importe quoi.



    Moi pour faire ça je ferais :
    • Prévoir un NSMutableSet dans ton @interface de ton UIViewController qui va stocker les indexPath des cellules
    • Initialiser ce NSMutableSet dans ton init
    • Dans ton didSelectRowAtIndexPath, regarder si le NSIndexPath en question est dans ton NSMutableSet. Si oui, l'enlever, si non, l'ajouter
    • Dans ton cellForRowAtIndexPath :
      • Quand tu alloc/init ta cell (dans le "if (cell == nil)"), mettre le selectionStyle de ta cell à  UITableViewCellSelectionStyleNone
      • Pour toutes les cell, recyclées ou non (en dehors du "if (cell == nil)"), régler ton accessoryType conformément au fait que ton ton NSMutableSet contient l'indexPath concerné (CheckMark) ou non (None).



    Comme ça tu gardes bien côté modèle (dans le NSMutableSet) l'ensemble des NSIndexPath correspondant aux éléments sélectionnés, et c'est bien décorellé de l'aspect affichage, où tu décides comment afficher les cellules sélectionnées ou non (aujourd'hui c'est avec des CheckMarks, demain ça sera p'tet avec des images en accessoryView, ou avec le selectionStyle ou avec un background ou une taille de police différents... mais ça c'est que la partie "Vue" du MVC dans cellForRowAtIndexPath, pas la partie gestion de la sélection avec le mode bascule "sélectionné / non sélectionné")
  • CeetixCeetix Membre
    mars 2012 modifié #4
    J'ai honte image/whip.gif' class='bbc_emoticon' alt=' >:) ' />

    Et si tu regarde du côté de
    -(UITableViewCellEditingStyle)tableView:(UITableView*)tableView editingStyleForRowAtIndexPath:(NSIndexPath*)indexPath
    




    Le sélection multiple ça revient à  faire une édition (comme pour delete les mails par exemple).
  • Alf1996Alf1996 Membre
    mars 2012 modifié #5
    Merci pour vos réponses... toujours aussi rapide !



    @ Aligator : ta solution me plais car effectivement elle respecte la règle du MVC. Je n'avais pas pensé au scroll, et effectivement, çà  fait des trucs bizarres !



    Par contre, j'avais toujours cette couleur bleue lorsque la cellule est sélectionnée... ce que j'ai résolu en faisant :
    <br />
    cell.selectionStyle=UITableViewCellSelectionStyleNone;<br />
    


    à  la création de la cell.

    Merci encore.



    Edit : oups, j'avais loupé une ligne en lisant ton post !!!!


    Quand tu alloc/init ta cell (dans le "if (cell == nil)"), mettre le selectionStyle de ta cell à  UITableViewCellSelectionStyleNone
  • Alf1996Alf1996 Membre
    mars 2012 modifié #6
    Bon, apparemment, j'ai encore dû faire une boulette...

    Je n'ai plus ma foutu couleur bleue, et mon NSMutableSet se rempli correctement, mais aucune trace de mes checkmarks, car en fait, une fois que la tableView est affichée, on ne passe plus dans "cellForRowAtIndexPath"

    Y a-t-il un moyen de forcer la tableView à  se "rafraichir" ?

  • Bah si tu passes dedans quand de nouvelles cell sont affichées lors du scroll.

    Pour rafraichir sinon c'est
    [tableView reloadData];
    
  • 'Alf1996' a écrit:


    Bon, apparemment, j'ai encore dû faire une boulette...

    Je n'ai plus ma foutu couleur bleue, et mon NSMutableSet se rempli correctement, mais aucune trace de mes checkmarks, car en fait, une fois que la tableView est affichée, on ne passe plus dans "cellForRowAtIndexPath"

    Y a-t-il un moyen de forcer la tableView à  se "rafraichir" ?




    Pas besoin de la rafraà®chir si :

    - ton code dans cellForRowAtIndexPath est approprié (ce qui doit être le cas)

    - tu mets à  jour la cell dans didSelectRowAtIndexPath: en même temps que tu mets à  jour ton set d'index. Sinon forcément ça ne marche pas (sauf à  faire un reload).
  • mars 2012 modifié #9
    Je ne sais pas quelle est la lourdeur de ta tableView (plusieurs sections?) mais il serait préférable dans ce cas d'utiliser -reloadRowsAtIndexPaths:withRowAnimation:

    En passant en paramètre -indexPathsForVisibleRows



    Mais encore une fois ça dépend vraiment de la lourdeur de ta table, les perfs seront meilleures avec un simple -reloadData si ta table est plutôt vide.



    Je n'ai pas suivi le sujet, mais comme Kuberman le précise, si tu ne cherches à  mettre à  jour qu'une cellule à  un instant T, alors -reloadRowsAtIndexPaths:withRowAnimation: sera l'idéal.
  • Alf1996Alf1996 Membre
    mars 2012 modifié #10
    J'avais essayé reloadData sans succès...



    @ ldesroziers : ce n'est pas une tableView très lourde (3 sections pour un total de 25 cellules) donc les perfs ne devraient pas être trop affectées, mais si çà  fonctionne, j'utiliserai la même technique sur une autre table qui, elle, pourrait être plus lourde...



    J'ai donc testé "reloadRowsAtIndexPaths" mais toujours sans succès...



    Malheureusement, je dois interrompre mes recherches pour l'instant, et je reprendrais çà  ce soir. En particulier, il faut que je vérifie que mon NSMutableSet se remplit correctement...

    Je vous tiendrai au courant.



    En tout cas, merci infiniment pour votre aide.
  • AliGatorAliGator Membre, Modérateur
    Erreur type : oubli d'alloc/init ton NSMutableSet (qui du coup est à  nil, donc [nil addObject:] ou [nil removeObject:] forcément ça fait rien image/tongue.png' class='bbc_emoticon' alt=':P' />)
  • 'AliGator' a écrit:


    Erreur type : oubli d'alloc/init ton NSMutableSet (qui du coup est à  nil, donc [nil addObject:] ou [nil removeObject:] forcément ça fait rien image/tongue.png' class='bbc_emoticon' alt=':P' />)




    Merci Ali... Effectivement j'aurais pu faire çà  ! ( je l'ai déjà  fait il n'y a pas si longtemps que çà  image/rolleyes.gif' class='bbc_emoticon' alt='::)' /> )

    En fait, j'ai trouvé une nouvelle erreur de Nioub ! Et oui, j'ai beaucoup d'imagination ! Je n'ajoutais jamais l'indexPath à  mon NSMutableSet (je faisais toujours la suppression, reste d'un copier/coller).



    Je joins le code final, si çà  peut aider quelqu'un :
    <br />
    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {<br />
    	return [allSections count];<br />
    }<br />
    -(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {<br />
    	return  [[myDict objectForKey:[allSections objectAtIndex:section]] count];<br />
    }<br />
    -(CGFloat) tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {<br />
    	return 40;  <br />
    }<br />
    -(NSString *) tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {<br />
    	return [allSections objectAtIndex:section];<br />
    }<br />
    -(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {<br />
    	static NSString *CellIdentifier = @&quot;Cell&quot;;<br />
    	UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];<br />
    	if (cell==nil) {<br />
    		cell=[[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];<br />
    		cell.selectionStyle=UITableViewCellSelectionStyleNone;<br />
    	}<br />
    	cell.textLabel.font=[UIFont systemFontOfSize:14.0];<br />
    	cell.textLabel.text=[[myDict objectForKey:[allSections objectAtIndex:indexPath.section]] objectAtIndex:indexPath.row];<br />
    	if ([listOfSelected containsObject:indexPath]) {<br />
    		cell.accessoryType=UITableViewCellAccessoryCheckmark;<br />
    	} else {<br />
    		cell.accessoryType=UITableViewCellAccessoryNone;<br />
    	}<br />
    	return cell;<br />
    }<br />
    -(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {<br />
    	if ([listOfSelected containsObject:indexPath]) {<br />
    		[listOfSelected removeObject:indexPath];<br />
    	} else {<br />
    		[listOfSelected addObject:indexPath];<br />
    	}<br />
    	[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:NO];<br />
    }<br />
    




    Sans oublier bien sûr les déclaration, initialisation et release (je n'utilise pas ARC) du NSMutableSet listOfSelected... image/kiss.gif' class='bbc_emoticon' alt=':-*' />
  • AliGatorAliGator Membre, Modérateur
    NB : le "cell.textLabel.font = .." peut aller à  l'intérieur du "if", pas la peine de rerégler la police à  chaque recyclage de cellule alors qu'elle est toujours la même d'une cellule à  l'autre image/wink.png' class='bbc_emoticon' alt=';)' />
  • 'AliGator' a écrit:


    NB : le "cell.textLabel.font = .." peut aller à  l'intérieur du "if", pas la peine de rerégler la police à  chaque recyclage de cellule alors qu'elle est toujours la même d'une cellule à  l'autre image/wink.png' class='bbc_emoticon' alt=';)' />


    Bien vu Ali. C'est vrai que çà  peut avoir son importance pour les perfos...

    Merci
  • AstoAsto Membre
    Un grand merci à  vous tous !



    Mes CheckMark faisaient vraiment n'importe quoi quand je faisais défiler mes tableaux... le code d'Alf1996 a tout résolu !
Connectez-vous ou Inscrivez-vous pour répondre.