UICollectionview单元格选择

XiO*_*iOS 18 ios uicollectionview

我已经制作了一个图像网格,为了显示其选择,我在选择时为图像绘制了边框.但问题是当我在顶部选择一些图像并向下滚动图像网格时,底部的其他一些图像似乎也被选中.下面是我的代码片段:

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];
Run Code Online (Sandbox Code Playgroud)

上面已添加到viewDidLoad中,其中集合视图单元格设计为nib.

并实施以下代表:

-(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;    
}
Run Code Online (Sandbox Code Playgroud)

我可以猜到重复使用单元格会出现问题,但不确定并且无法解决问题.等待任何形式的帮助和建议.

提前致谢.

Rob*_*Rob 41

我不明白为什么会这样.我不相信问题是使用rowvs item,尽管你真的应该使用item.但是,我可以想象,如果你的集合视图有多个section,那只看row/ item但忽略section会是一个问题(即它会item每个中 选择相同的数字section).

为了削减戈尔迪结,我建议保存NSIndexPath所选项目,然后使用它作为比较的基础.这也使得渲染优化变得容易didSelectItemAtIndexPath.无论如何,首先定义你的财产:

@property (nonatomic, strong) NSIndexPath *selectedItemIndexPath;
Run Code Online (Sandbox Code Playgroud)

然后实施cellForItemAtIndexPathdidSelectItemAtIndexPath:

- (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];
}
Run Code Online (Sandbox Code Playgroud)

顺便说一句,请注意我并没有搞乱这个tag属性(我认为没有价值).另请注意,我不是重新加载整个集合视图,而是仅重新加载所选单元格(如果还有一个先前选定的单元格,那也应该更高效).