web-dev-qa-db-fra.com

UICollectionView shouldSelectItemAtIndexPath = NO n'empêche pas la désélection de l'ancienne sélection?

J'ai plusieurs éléments dans un CollectionView, mais seuls quelques-uns d'entre eux devraient être sélectionnables. Je gère cela avec la méthode delegate:

- (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath

Mon problème se produit si un élément sélectionnable est sélectionné et qu'à l'étape suivante, la sélection d'un élément non sélectionnable est rejetée par shouldSelectItemAtIndexPath qui renvoie NON, l'élément sélectionné est désélectionné.

J'ai aussi essayé d'utiliser

- (BOOL)collectionView:(UICollectionView *)collectionView shouldHighlightItemAtIndexPath:(NSIndexPath *)indexPath

Mais c'est le même problème.

Est-ce le comportement souhaité correct de UICollectionView? Et si oui, comment puis-je éviter la désélection de mon dernier élément sélectionné si un élément non sélectionnable est sélectionné?

28
sust86

Je dois corriger mon hypothèse: La dernière sélection ne sera pas désélectionnée!  

Afin de changer l'apparence de la cellule lors de la sélection, j'ai remplacé l'accesseur setSelected de UICollectionViewCell. Lors de la sélection d'un élément non sélectionnable, l'accesseur setSelected de la dernière cellule sélectionnée est appelé plusieurs fois. D'abord avec l'état NON, puis avec l'état OUI et finalement encore avec NON. Le dernier état NO a amené ma cellule à définir son apparence sur celle d'une cellule non sélectionnée.

Je ne connais pas la raison de ce comportement étrange et je ne pourrais pas le résoudre.

Ma solution de contournement consiste à modifier l'apparence des cellules sélectionnées directement dans le ViewController.

Définir l'apparence sélectionnée dans:

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath

Supprimer l'apparence sélectionnée:

- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath

Vérifiez si la cellule actuelle est sélectionnée et modifiez l'apparence comme prévu.

   - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
13
sust86

J'ai résolu ce problème en définissant self.collectionView.allowsMultipleSelection = true.

Et désélectionner chaque index à mon retour true à -collectionView:shouldSelectItemAtIndexPath:

1
Gustavo Vergara

Vous devez modifier l'apparence des cellules dans les méthodes déléguées DidSelect et DidDeselect. Si return NO dans la méthode shouldSelect, DidSelect et DidDeselect ne seront pas appelés, ainsi l'apparence restera la même, en cohérence avec le statut sélectionné de collectionView.

1
jx ch

Je viens d'avoir ce même problème. J'ai essayé diverses solutions et la première qui a fonctionné dans mon cas était de recharger puis de resélectionner les cellules sélectionnées. Cela a fonctionné pour moi que je recharge toute la vue de la collection ou uniquement les cellules bloquées avec une apparence non sélectionnée.

Des approches qui n'ont pas fonctionné pour moi:

  • Définir la propriété selected de la cellule sur true, ou même basculer entre false puis true à nouveau.
  • Sélectionner l'élément via -selectItemAtIndexPath:animated:scrollPosition: ou même le désélectionner via -deselectItemAtIndexPath: et le sélectionner à nouveau.
  • Recharger uniquement les lignes sélectionnées avec -reloadItemsAtIndexPaths:
  • Recharger tout avec -reloadData.
1
Andrew Hershberger

Je ne sais pas pourquoi UICollectionView est si désordonné comme ceci comparé à UITableViewController... Quelques choses que j'ai découvertes.

La raison pour laquelle - setSelected: est appelée à plusieurs reprises est due aux méthodes de séquence. La séquence est très similaire à celle des méthodes UITextFieldDelegate.

La méthode - collectionView:shouldSelectItemAtIndexPath: est appelée avant que la collectionView sélectionne réellement la cellule car elle demande en fait "doit-elle être sélectionnée"?

- collectionView:didSelectItemAtIndexPath: est en fait appelé après que la collectionView ait sélectionné la cellule. D'où le nom "choisi".

Même chose pour la désélection.

TL; DR - Demandez à votre collectionView de désélectionner la cellule dans la méthode de délégation - collectionView:shouldSelectItemAtIndexPath: en appelant - selectItemAtIndexPath:animated:scrollPosition: et tout ira bien.

1
funct7

6 ans de retard, mais peut-être utile à quelqu'un d'autre. Dans des cas comme celui-ci, où certaines cellules ne devraient pas être sélectionnables en premier lieu, on peut simplement ajouter isUserInteractionEnabled = false à la fonction personnalisée UICollectionViewCell's awakeFromNib(). Cela peut aussi être fait dans le fichier xib mais c'est moins explicite et cela pourrait ne pas être évident pour les futurs responsables.

0
Orr Matarasso

As-tu essayé:

- (BOOL)collectionView:(UICollectionView *)collectionView shouldDeselectItemAtIndexPath:(NSIndexPath *)indexPath

J'ai trouvé que cela fonctionnait comme souhaité. 

0
user2887309