UICollectionView选择和取消选择问题

bwo*_*rby 46 cocoa-touch ios uicollectionview

所以我有一个主要对象,它有许多与之相关的图像.图像也是一个对象.

假设您有一个集合视图控制器,并且在该控制器中

cellForItemAtIndexPath

基于主要对象,如果它具有与之关联的当前图像,我想将selected设置为true.但我希望用户能够随时"取消选择"当前单元格以删除与主对象的关联.

我发现如果你设置"selected to true" - 如果主对象和图像之间存在关系cellForItemAtIndexPath,则取消选择不再是一个选项.

didDeselectItemAtIndexPath
Run Code Online (Sandbox Code Playgroud)

didSelectItemAtIndexPath
Run Code Online (Sandbox Code Playgroud)

我用日志测试它是否被调用.如果一个单元格设置为选中 - nether被调用,但是如果我从未将单元格设置为选中,cellForItemAtIndexPath我可以选择并取消选择我想要的全部单元格.

这是集合视图应该工作的预期方式吗?我阅读了文档,似乎并没有谈到这一点.我解释文档意味着它的工作方式与表视图单元格相同.有一些明显的变化

这也表明控制器设置正确,并使用适当的委托方法....嗯

小智 86

我有同样的问题,即.设置cell.selected = YES[UICollectionView collectionView:cellForItemAtIndexPath:]那么不能够通过点击它来取消细胞.

解决方案现在:我打电话 [UICollectionViewCell setSelected:][UICollectionView selectItemAtIndexPath:animated:scrollPosition:][UICollectionView collectionView:cellForItemAtIndexPath:].

  • 有人提出了更好的解决方案吗?这个解决方案也适用于我,但这可能是一个错误. (6认同)
  • 你是个圣人!一个SAINT我告诉你!不确定ScrollPosition枚举的具体情况,但它的工作原理.(Y) (3认同)
  • 奇怪的是它应该是必要的 - 但它的工作原理..并且它不会导致带有didSelectItemAtIntexPath委托的无限循环. (2认同)

Ane*_*eel 46

setSelected你的Cell课程中有自定义方法吗?你[super setSelected:selected]在用这种方法打电话吗?

我有一个神秘的问题,我在使用多个选择,一旦被选中,我就无法取消选择.调用super方法修复了问题.

  • 经过5年的艰苦iOS编程,我无法相信我错过了一些如此明显的东西.咄! (8认同)
  • 这是我的问题! (2认同)
  • 这很容易错过 (2认同)

Fjo*_*ohn 45

我有一个Deselect问题,UICollectionView我发现我不允许在collectionView上进行多项选择.因此,当我进行测试时,我总是尝试在同一个单元格上,如果单个选择为ON,则无法取消选择已选择的单元格.

我不得不补充:

myCollectionView.allowsMultipleSelection = YES;
Run Code Online (Sandbox Code Playgroud)


dml*_*ron 35

这有点旧,但是,因为我使用swift遇到同样的问题,我会添加我的答案.使用时:

 collectionView.selectItemAtIndexPath(indexPath, animated: true, scrollPosition: [])
Run Code Online (Sandbox Code Playgroud)

细胞根本没有被选中.但使用时:

cell.selected = true
Run Code Online (Sandbox Code Playgroud)

它确实被选中但我无法再选择/取消选择该单元格.

我的解决方案(使用两种方法):

cell.selected = true
collectionView.selectItemAtIndexPath(indexPath, animated: true, scrollPosition: .None)
Run Code Online (Sandbox Code Playgroud)

调用这两种方法时:

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
Run Code Online (Sandbox Code Playgroud)

它工作得很好!


fun*_*ct7 10

我不知道为什么UICollectionView这样凌乱如此UITableViewController......我发现了一些事情.

setSelected:多次调用的原因是因为调用了序列方法.序列与UITextFieldDelegate方法非常相似.

collectionView:shouldSelectItemAtIndexPath:collectionView实际选择单元格之前调用该方法,因为它实际上在询问"应该选择它"吗?

collectionView:didSelectItemAtIndexPath:实际上在collectionView选择单元格后调用.因此,名称"确实选择".

所以这就是你的情况(我的情况,我不得不在这个问题上花费数小时).

用户再次触摸所选单元格以取消选择.shouldSelectItemAtIndexPath:调用以检查是否应该选择单元格.在collectionView选择该小区,然后didSelectItemAtIndexPath被调用.无论你在这一点做什么都是在单元格selected属性设置为之后YES.这就是为什么类似的东西cell.selected = !cell.selected不起作用的原因.

TL; DR - 通过调用并返回collectionView,在委托方法中取消选择单元格.collectionView:shouldSelectItemAtIndexPath:deselectItemAtIndexPath:animated:NO

我所做的简短例子:

- (BOOL)collectionView:(OPTXListView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath {
    NSArray *selectedItemIndexPaths = [collectionView indexPathsForSelectedItems];

    if ([selectedItemIndexPaths count]) {
        NSIndexPath *selectedIndexPath = selectedItemIndexPaths[0];

        if ([selectedIndexPath isEqual:indexPath]) {
            [collectionView deselectItemAtIndexPath:indexPath animated:YES];

            return NO;
        } else {
            [collectionView selectItemAtIndexPath:indexPath animated:YES scrollPosition:UICollectionViewScrollPositionCenteredHorizontally];

            return YES;
        }
    } else {
        [collectionView selectItemAtIndexPath:indexPath animated:YES scrollPosition:UICollectionViewScrollPositionCenteredHorizontally];

        return YES;
    }
}
Run Code Online (Sandbox Code Playgroud)


Tre*_*ent 7

这是我对Swift 2.0的回答.

我能够在viewDidLoad()中设置以下内容

collectionView.allowsMultipleSelection = true;
Run Code Online (Sandbox Code Playgroud)

然后我实现了这些方法

func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
    let cell = collectionView.cellForItemAtIndexPath(indexPath) as! MyCell
    cell.toggleSelected()
}

func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath) {
    let cell = collectionView.cellForItemAtIndexPath(indexPath) as! MyCell
    cell.toggleSelected()
}
Run Code Online (Sandbox Code Playgroud)

最后

class MyCell : UICollectionViewCell {

    ....

    func toggleSelected ()
    {
        if (selected){
            backgroundColor = UIColor.orangeColor()
        }else {
            backgroundColor = UIColor.whiteColor()
        }
    }

}
Run Code Online (Sandbox Code Playgroud)


Rya*_*yne 6

这个问题已经有六年了,但我不在乎;到达这里并发现没有一个答案可以解决我的具体问题后,我最终想到了我认为是这个问题的最佳答案。所以,我将其发布在这里,供后代使用。

由于 UICollectionView 调用该方法的方式,在 cellForItemAtIndexPath 中选择单元格是有问题的。它不仅仅在最初设置集合视图时被调用。当集合视图滚动时,它会被连续调用,因为集合视图只向其数据源询问可见单元格,从而节省了大量开销。

由于集合视图不会将所有单元格保存在内存中,因此它们需要管理自己单元格的选定状态。他们不希望您向他们提供已设置 isSelected 属性的单元格。他们希望您向他们提供单元格,并且如果合适,他们将在其上设置选定的属性。

这就是为什么 Apple 警告您不要直接设置 UICollectionViewCell 的 isSelected 属性。UICollectionView 希望为您解决这个问题。

所以,答案是不要尝试在 cellForItemAtIndexPath 方法中选择单元格。选择要最初选择的单元格的最佳位置是 UICollectionViewController 的 viewWillAppear 方法。在该方法中,通过调用 UICollectionView.selectItem(at:animated:scrollPosition:) 选择所有所需的单元格,并且不要直接在单元格上设置 isSelected 。


Reg*_*ion 1

我不知道我是否理解这个问题,但选定的状态是每个单元格设置的,并且将包括单元格内的所有子视图。您没有解释“主要对象有许多与之相关的图像”的含义。与子视图中的关联?或者你到底指的是哪种关联?

对我来说这听起来像是一个设计问题。也许您需要一个 UIView 子类,其中包含您需要的任何关联对象;然后可以将该子类设置为内容视图。例如,我会在有图像、描述以及与图像相关的录音的情况下执行此操作。所有这些都在子类中定义,然后每个子类都成为单个单元格的内容视图。

我还使用了一种安排将图像关联到包含它们的文件夹。在此设置下,文件夹和图像各自具有一个子类,并且任一子类都可以作为内容视图附加到单元格(这些作为单个实体存储在核心数据中)。

也许你可以进一步解释你的问题?