UICollectionViewselect并取消select问题

所以我有一个主要的对象,有许多图像相关联。 一个图像也是一个对象。

假设你有一个集合视图控制器,并且在你拥有的控制器中

cellForItemAtIndexPath

以及基于主要的对象,如果它有与之相关的当前图像,我想设置为true。 但是我希望用户能够在任何时候“取消”当前单元格以取消与主要对象的关联。

我发现如果你设置“select为真” – 如果主要对象和cellForItemAtIndexPath图像之间有关系,取消select不再是一个选项。

 didDeselectItemAtIndexPath 

 didSelectItemAtIndexPath 

我testing一个日志,看看他们是否被称为。 如果一个单元格被设置为选中 – 下一个被调用,但如果我从来没有设置单元格在cellForItemAtIndexPath中select我可以select和取消select所有我想要的。

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

这也显示控制器设置正确,并使用适当的代表方法….嗯

我有同样的问题,即。 在[UICollectionView collectionView:cellForItemAtIndexPath:]设置cell.selected = YES ,则不能通过点击取消select该单元格。

现在的解决scheme:我在[UICollectionView collectionView:cellForItemAtIndexPath:] 同时调用 [UICollectionViewCell setSelected:][UICollectionView selectItemAtIndexPath:animated:scrollPosition:] [UICollectionView collectionView:cellForItemAtIndexPath:]

你的Cell类中有一个自定义的setSelected方法吗? 你在那个方法中调用[super setSelected:selected]

我有一个神秘的问题,我正在使用多个select,一旦选中它,我就无法取消select单元格。 调用超级方法解决了这个问题。

我有一个UICollectionView取消select问题,我发现我不允许在collectionView上的多个select。 所以当我testing的时候,我总是试着在同一个单元格上,如果单个select是ON,你就不能取消已经select的单元格。

我不得不补充:

 myCollectionView.allowsMultipleSelection = YES; 

这是有点老,但是,因为我遇到同样的问题,使用迅速我会加我的答案。 使用时:

  collectionView.selectItemAtIndexPath(indexPath, animated: true, scrollPosition: []) 

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

 cell.selected = true 

它确实被选中,但我无法再select/取消select该单元格。

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

 cell.selected = true collectionView.selectItemAtIndexPath(indexPath, animated: true, scrollPosition: .None) 

当这两个方法被调用时:

 func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell 

它完美的工作!

这是我对Swift 2.0的回答。

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

 collectionView.allowsMultipleSelection = true; 

然后我实现了这些方法

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

最后

 class MyCell : UICollectionViewCell { .... func toggleSelected () { if (selected){ backgroundColor = UIColor.orangeColor() }else { backgroundColor = UIColor.whiteColor() } } } 

我不知道为什么UICollectionView是如此混乱像UITableViewController相比…我发现了一些事情。

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

方法collectionView:shouldSelectItemAtIndexPath:collectionView实际select单元之前被调用,因为它实际上是在询问“它应该被选中”吗?

collectionView:didSelectItemAtIndexPath:实际上是在collectionViewselect单元格之后调用的。 因此,名称“确实select”。

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

用户再次触摸所选单元格以取消select。 shouldSelectItemAtIndexPath:调用shouldSelectItemAtIndexPath:来检查是否应该select单元格。 collectionViewselect单元格,然后调用didSelectItemAtIndexPath 。 无论你在这一点做什么是在单元格的selected属性设置为YES 。 这就是为什么像cell.selected = !cell.selected不会工作。

TL; DR – 让你的collectionView取消select委托方法中的单元格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; } } 

生活在iOS 9的时代,有很多事情要检查这里。

  1. 检查你有没有collectionView.allowsSelection设置为YES
  2. 检查你有没有collectionView.allowsMultipleSelection设置为YES (如果你需要这种能力)

现在来粉丝部分。 如果你听苹果,并设置cell.contentView而不是cell本身,那么你已经隐藏其selectedBackgroundView永远不可见。 因为:

 (lldb) po cell.selectedBackgroundView <UIView: 0x7fd2dae26bb0; frame = (0 0; 64 49.5); autoresize = W+H; layer = <CALayer: 0x7fd2dae26d20>> (lldb) po cell.contentView <UIView: 0x7fd2dae22690; frame = (0 0; 64 49.5); gestureRecognizers = <NSArray: 0x7fd2dae26500>; layer = <CALayer: 0x7fd2dae1aca0>> (lldb) pviews cell <MyCell: 0x7fd2dae1aa70; baseClass = UICollectionViewCell; frame = (0 0; 64 49.5); clipsToBounds = YES; hidden = YES; opaque = NO; layer = <CALayer: 0x7fd2dae1ac80>> | <UIView: 0x7fd2dae26bb0; frame = (0 0; 64 49.5); autoresize = W+H; layer = <CALayer: 0x7fd2dae26d20>> | <UIView: 0x7fd2dae22690; frame = (0 0; 64 49.5); gestureRecognizers = <NSArray: 0x7fd2dae26500>; layer = <CALayer: 0x7fd2dae1aca0>> | | <UIView: 0x7fd2dae24a60; frame = (0 0; 64 49.5); clipsToBounds = YES; alpha = 0; autoresize = RM+BM; userInteractionEnabled = NO; layer = <CALayer: 0x7fd2dae1acc0>> | | <UILabel: 0x7fd2dae24bd0; frame = (0 0; 64 17.5); text = '1'; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x7fd2dae240c0>> | | <UILabel: 0x7fd2dae25030; frame = (0 21.5; 64 24); text = '1,04'; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x7fd2dae25240>> (lldb) po cell.contentView.backgroundColor UIDeviceRGBColorSpace 0.4 0.4 0.4 1 

所以,如果你想使用selectedBackgroundView(这是打开/closures与cell.selectedselectItemAtIndexPath... )然后执行此操作:

 cell.backgroundColor = SOME_COLOR; cell.contentView.backgroundColor = [UIColor clearColor]; 

它应该工作得很好。

我不知道我理解这个问题,但是选定的状态是为每个单元格设置的,并且会包含单元格内的所有子视图。 你不能解释你的意思是“一个主要的物体有许多与之相关的图像”。 关联在子视图? 或者你是什么意思?

这听起来像是一个devise问题。 也许你需要一个包含你需要的任何关联对象的UIView子类; 该子类可以被设置为内容视图。 我这样做,例如,我有一个图像,描述和与图像有关的录音。 所有都在子类中定义,然后每个这些子类成为单个单元格的内容视图。

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

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

你看过吗:

 - (BOOL)collectionView:(PSTCollectionView *)collectionView shouldDeselectItemAtIndexPath:(NSIndexPath *)indexPath; 

请更清楚地说明你的问题,也许我们可以把它弄清楚。 我刚刚花了一些时间与UICollectionView。

我认为你的问题可能是由于混淆,如果你设置cell.selected = YES编程,原因didSelectItemAtIndexPath:没有得到调用是因为只有当collectionView本身负责细胞的select(例如通过一个TAP)。

  func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) { let cell = collectionView.cellForItemAtIndexPath(indexPath) if cell?.selected == true{ cell?.layer.borderWidth = 4.0 cell?.layer.borderColor = UIColor.greenColor().CGColor } }func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath) { let cell = collectionView.cellForItemAtIndexPath(indexPath) if cell?.selected == false{ cell?.layer.borderColor = UIColor.clearColor().CGColor } } 

我find简单的解决scheme

我正在使用自定义单元格子类,对于我来说,我只需要在子类中的prepareForReuse()中设置self.selected = false

单元格select和取消select最好通过设置一个backgroundView和一个选定的背景视图来处理。 我build议确保在layoutSubviews方法中正确设置这两个视图的框架(如果您通过IB设置选定视图和背景视图)。

不要忘了设置你的contentView的(如果你有一个)背景颜色清除,以便正确的背景视图显示。

不要直接设置单元格的select(即通过cell.selected = YES),在集合视图中使用为此devise的方法。 文件中有清楚的解释,尽pipe我会同意这些指南中的信息有些分散。

你不应该直接在你的collectionView数据源中捅入单元格的背景颜色。

另外,最后要注意的是,如果你在你的单元的类中实现了这些,不要忘记调用[super prepareForReuse]和[super setSelected:selected],因为你可能会阻止单元的超类进行单元select。

打我,如果你需要进一步澄清这个问题。

[UICollectionView collectionView:cellForItemAtIndexPath:]同时调用[UICollectionViewCell setSelected:][UICollectionView selectItemAtIndexPath:animated:scrollPosition:]不起作用,请尝试在dispatch_async(dispatch_get_main_queue(), ^{});调用它们dispatch_async(dispatch_get_main_queue(), ^{}); 块。

这就是最终为我解决的问题。