【问题标题】:UICollectionview cell selectionUICollectionview 单元格选择
【发布时间】:2017-07-08 14:10:31
【问题描述】:

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

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

以上已添加到 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;    
}

我可以猜到重用单元格出了点问题,但不确定也想不出解决问题的想法。 等待任何形式的帮助和建议。

提前致谢。

【问题讨论】:

  • 尝试使用 indexPath.item 代替 indexPath.row。如果您仍然遇到任何问题,请告诉我
  • 感谢您的建议 Anurag,但 indexpath.item 的工作方式仍然与 indexpath.row 相同......

标签: ios uicollectionview


【解决方案1】:

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

要快刀斩乱麻,我建议保存所选项目的NSIndexPath,然后将其用作比较的基础。这也使得在didSelectItemAtIndexPath 中进行优化变得容易。无论如何,首先定义你的属性:

@property (nonatomic, strong) NSIndexPath *selectedItemIndexPath;

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

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

【讨论】:

  • 嗨,Rob,这就像任何事情一样......而且你的解决方案给出了明确的解决方案,即使在 tableview 的东西中也消除了我的大部分困惑......非常感谢!太好了!!!!!!
  • 嗨,当我在集合视图中选择其他单元格时,didDeselectItemAtIndexPath 似乎没有被调用。我正在尝试在 didDeselectItemAtIndexPath 中做一些工作,因为当我双击单元格以取消选择它时,上面的代码会崩溃。我确信我已经正确设置了代表。有什么解决方案可以避免这种崩溃或调用 collectionview 好友的“取消选择”委托?
  • @XiOS 您只需更改didSelectItemAtIndexPath 即可在再次点击同一项目时进行处理。请参阅修改后的答案。
  • Rob,这是在 UICollectionView 上处理选择的最动态方式吗?当您选择单元格时会怎样。从其余单元格中手动删除“选择”?或者它也是一个重用问题?
  • 我不知道我是否错了,但框架应该为我工作,但您的解决方案可以按我的意愿工作,谢谢!!!罗伯。
【解决方案2】:

这段代码在 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

【讨论】:

    猜你喜欢
    • 2019-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多