j'ai fait une grille d'images et afin de montrer sa sélection, j'ai dessiné une bordure pour l'image sélectionnée. mais le problème est que lorsque je sélectionne une image en haut et que je fais défiler la grille des images, une autre image en bas semble également être sélectionnée. Voici l'extrait de code:
UINib *cellNib = [UINib nibWithNibName:@"collectionCell" bundle:nil];
[self.collectionView registerNib:cellNib forCellWithReuseIdentifier:@"cellCV"];
UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
[flowLayout setItemSize:CGSizeMake(95, 95)];
[flowLayout setScrollDirection:UICollectionViewScrollDirectionVertical];
[self.collectionView setCollectionViewLayout:flowLayout];
Ci-dessus a été ajouté dans viewDidLoad avec la cellule de vue de collection conçue dans nib.
et mis en œuvre par les délégués suivants:
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
selectedImageIndex = indexPath.row;
[collectionView reloadData];
}
-(CollectionCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UIImage *img = [imageArray objectAtIndex:indexPath.row];
static NSString *cellIdentifier = @"cellCV";
CollectionCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:
cellIdentifier forIndexPath:indexPath];
cell.imageView.image = img;
cell.imageView.tag = indexPath.row;
UIImageView *imgView = (UIImageView *)[cell viewWithTag:indexPath.row];
if (indexPath.row == selectedImageIndex) {
imgView.layer.borderWidth = 4.0;
imgView.layer.borderColor = [UIColor redColor].CGColor;
NSLog(@"selected indexpath: %d", indexPath.row);
}
else {
imgView.layer.borderWidth = 0.0;
imgView.layer.borderColor = nil;
}
return cell;
}
je pourrais deviner que quelque chose ne va pas avec la réutilisation de la cellule, mais je ne suis pas sûr et je ne pourrais pas avoir une idée pour le résoudre . En attente de tout type d'aide et de suggestions.
Merci d'avance.
Je ne vois pas pourquoi cela se produirait. Je ne crois pas que le problème réside dans l'utilisation de row
contre item
, bien que vous devriez vraiment utiliser item
. Cependant, je peux imaginer que si votre vue de collection comporte plus d'une variable section
, le fait de ne regarder que la variable row
/item
mais de ne pas tenir compte de section
constituerait un problème (c'est-à-dire qu'il sélectionnerait le même nombre item
dans tous section
).
Pour couper le nœud gordien, je suggérerais de conserver la NSIndexPath
de l'élément sélectionné, puis de l'utiliser comme base de comparaison. Cela facilite également le rendu d'une optimisation dans didSelectItemAtIndexPath
. Quoi qu'il en soit, commencez par définir votre propriété:
@property (nonatomic, strong) NSIndexPath *selectedItemIndexPath;
Et puis implémentez cellForItemAtIndexPath
et didSelectItemAtIndexPath
:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = @"Cell";
CollectionCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
cell.imageView.image = ...
if (self.selectedItemIndexPath != nil && [indexPath compare:self.selectedItemIndexPath] == NSOrderedSame) {
cell.imageView.layer.borderColor = [[UIColor redColor] CGColor];
cell.imageView.layer.borderWidth = 4.0;
} else {
cell.imageView.layer.borderColor = nil;
cell.imageView.layer.borderWidth = 0.0;
}
return cell;
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
// always reload the selected cell, so we will add the border to that cell
NSMutableArray *indexPaths = [NSMutableArray arrayWithObject:indexPath];
if (self.selectedItemIndexPath)
{
// if we had a previously selected cell
if ([indexPath compare:self.selectedItemIndexPath] == NSOrderedSame)
{
// if it's the same as the one we just tapped on, then we're unselecting it
self.selectedItemIndexPath = nil;
}
else
{
// if it's different, then add that old one to our list of cells to reload, and
// save the currently selected indexPath
[indexPaths addObject:self.selectedItemIndexPath];
self.selectedItemIndexPath = indexPath;
}
}
else
{
// else, we didn't have previously selected cell, so we only need to save this indexPath for future reference
self.selectedItemIndexPath = indexPath;
}
// and now only reload only the cells that need updating
[collectionView reloadItemsAtIndexPaths:indexPaths];
}
En passant, notez que je ne plaisante pas avec la propriété tag
(je n'y vois aucune valeur). Notez également que plutôt que de recharger l'intégralité de la vue de collection, je ne fais que recharger la cellule sélectionnée (et s'il y avait une cellule précédemment sélectionnée, celle-ci aussi), ce qui devrait être plus efficace.
Ce code est dans Swift 3:
if self.selectedItemIndexPath != nil && indexPath.compare(self.selectedItemIndexPath) == .orderedSame {
cell.imageView!.layer.borderColor = UIColor.red.cgColor
cell.imageView!.layer.borderWidth = 4.0
} else {
cell.imageView!.layer.borderColor = nil
cell.imageView!.layer.borderWidth = 0.0
}
return cell