ios UICollectionview 单元格选择

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18857167/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 01:17:44  来源:igfitidea点击:

UICollectionview cell selection

iosuicollectionview

提问by XiOS

i have made a grid of images and in order to show its selection i drew border for the image when selected. but the problem is when i select some image at the top and scroll down the grid of images, some other image at the bottom also seemed to be selected. below is my code snippet:

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

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];

Above has been added in viewDidLoad with the collection view cell designed in nib.

上面已经在 viewDidLoad 中添加了在 nib 中设计的集合视图单元格。

and implemented following delegates:

并实施了以下代表:

-(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;    
}

i could guess that something is going wrong with reusing the cell, but not sure and couldnt het an idea to resolve it. Waiting for any kind of help and suggestions.

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

Thanks in advance.

提前致谢。

回答by Rob

I'm not seeing why this would take place. I do not believe the issue is the use of rowvs item, though you really should use item. I can imagine, though, if your collection view has more than one section, that only looking at row/itembut ignoring sectionwould be a problem (i.e. it would select the same itemnumber in everysection).

我不明白为什么会发生这种情况。我不相信问题在于rowvs的使用item,尽管您确实应该使用item. 但是,我可以想象,如果您的集合视图有多个section,那么只查看row/item但忽略section将是一个问题(即它会item每个 中选择相同的数字section)。

To cut the Gordian knot, I'd suggest saving the NSIndexPathof the selected item, and then using that for the basis of comparison. That also makes it easy to render an optimization in didSelectItemAtIndexPath. Anyway, first define your property:

为了解决这个问题,我建议保存NSIndexPath所选项目的 ,然后将其用作比较的基础。这也使得在didSelectItemAtIndexPath. 无论如何,首先定义你的财产:

@property (nonatomic, strong) NSIndexPath *selectedItemIndexPath;

And then implement cellForItemAtIndexPathand didSelectItemAtIndexPath:

然后实现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];
}

As an aside, note that I'm not messing around with the tagproperty (I see no value in that). Also note that rather than reloading entire collection view, I'm only reloading the selected cell (and if there was a previous selected cell, that one too), which should be more efficient.

顺便说一句,请注意,我并没有在弄乱tag财产(我认为这没有任何价值)。另请注意,我只是重新加载选定的单元格,而不是重新加载整个集合视图(如果有之前选定的单元格,那也是),这应该更有效。

回答by Phung Du

This code is in Swift 3:

此代码在 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