所以我有一个主要对象,它有许多与之关联的图像。图像也是一个对象。
假设您有一个集合视图控制器,并且在该控制器中有
cellForItemAtIndexPath
基于主要对象,如果它具有与之关联的当前图像,我想将selected设置为true。但我希望用户能够随时“取消选择”当前单元格以删除与主对象的关联。
我发现如果你设置“selected to true” - 如果cellForItemAtIndexPath
中的主要对象和图像之间存在关系,则取消选择不再是一种选择。
in
didDeselectItemAtIndexPath
和
didSelectItemAtIndexPath
我用日志测试是否被调用。如果一个单元格被设置为选中 - nether被调用,但如果我从未在cellForItemAtIndexPath
中设置一个单元格,我可以选择并取消选择我想要的所有单元格。
这是集合视图应该起作用的预期方式吗?我阅读了文档,似乎并没有谈到这一点。我解释文档意味着它的工作方式与表视图单元格相同。有一些明显的变化
这也表明控制器设置正确并使用适当的委托方法.... hmmmm
答案 0 :(得分:84)
我有同样的问题,即。在cell.selected = YES
中设置[UICollectionView collectionView:cellForItemAtIndexPath:]
,然后点击它就无法取消选择该单元格。
现在的解决方案:我在[UICollectionViewCell setSelected:]
中拨打 [UICollectionView selectItemAtIndexPath:animated:scrollPosition:]
和[UICollectionView collectionView:cellForItemAtIndexPath:]
。
答案 1 :(得分:45)
我遇到了UICollectionView
的取消选择问题,我发现我不允许在collectionView上进行多项选择。因此,当我进行测试时,我总是在同一个单元格上尝试,如果单个选择为ON,则无法取消选择已选择的单元格。
我不得不补充道:
myCollectionView.allowsMultipleSelection = YES;
答案 2 :(得分:43)
您的Cell类中是否有自定义setSelected
方法?你在那个方法中调用[super setSelected:selected]
吗?
我有一个神秘的问题,我正在使用多项选择,一旦被选中,我就无法取消选择。调用super方法解决了这个问题。
答案 3 :(得分:32)
这有点老了但是,因为我使用swift遇到同样的问题,我会添加我的答案。 使用时:
collectionView.selectItemAtIndexPath(indexPath, animated: true, scrollPosition: [])
细胞根本没有被选中。但是在使用时:
cell.selected = true
它确实被选中但我无法再选择/取消选择该单元格。
我的解决方案(使用两种方法):
cell.selected = true
collectionView.selectItemAtIndexPath(indexPath, animated: true, scrollPosition: .None)
当调用这两种方法时:
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
它完美无缺!
答案 4 :(得分:10)
与UICollectionView
相比,我不知道为什么UITableViewController
如此混乱......
我发现了一些事情。
多次调用setSelected:
的原因是因为调用了序列方法。该序列与UITextFieldDelegate
方法的序列非常相似。
在collectionView:shouldSelectItemAtIndexPath:
实际选择单元格之前调用方法collectionView
,因为它实际上在询问“应该选择它”吗?
collectionView:didSelectItemAtIndexPath:
选择单元格后调用{p> 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;
}
}
答案 5 :(得分:7)
这是我对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()
}
}
}
答案 6 :(得分:2)
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
}
}
我发现的简单解决方案
答案 7 :(得分:2)
生活在iOS 9时代,这里有很多东西需要检查。
collectionView.allowsSelection
设置为YES
collectionView.allowsMultipleSelection
设置为YES
(如果您需要此功能)现在是粉丝部分。
如果您听取Apple并在backgroundColor
上设置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(使用cell.selected
和selectItemAtIndexPath...
打开/关闭的那个),请执行以下操作:
cell.backgroundColor = SOME_COLOR;
cell.contentView.backgroundColor = [UIColor clearColor];
它应该可以正常工作。
答案 8 :(得分:1)
我不知道我理解了这个问题,但是每个单元格都设置了选定状态,并且包含了单元格中的所有子视图。你没有解释你的意思“主要对象有很多与之相关的图像。”在子视图中关联?或者你究竟是什么样的联想?
这听起来像是一个设计问题。也许你需要一个UIView子类,它包含你需要的任何相关对象;然后可以将该子类设置为内容视图。我这样做,例如,我有一个图像,描述和与图像相关的录音。所有都在子类中定义,然后每个子类成为单个单元格的内容视图。
我还使用相关图像的排列到包含它们的文件夹。在此设置下,文件夹和图像均具有子类,并且其中一个可以作为内容视图附加到单元格(这些作为单个实体存储在核心数据中)。
也许你可以进一步解释你的问题?
答案 9 :(得分:1)
- (BOOL)collectionView:(PSTCollectionView *)collectionView shouldDeselectItemAtIndexPath:(NSIndexPath *)indexPath;
请更清楚地说明您的问题,也许我们可以深入了解它。我刚刚在UICollectionView上花了一些时间。
我认为你的问题可能源于这样的困惑:如果你以编程方式设置cell.selected = YES
,那么didSelectItemAtIndexPath:
未被调用的原因是因为只有当collectionView本身负责单元格时才会使用#39;选择(例如通过点击)。
答案 10 :(得分:1)
我正在使用自定义单元格子类,对我来说,我只需要在子类中的self.selected = false
中设置prepareForReuse()
。
答案 11 :(得分:1)
这个问题已经六岁了,但是我不在乎;在到达这里并发现没有答案可以解决我的特定问题后,我最终找到了我认为是该问题的最佳答案。因此,我将其张贴在这里以供后代使用。
由于UICollectionView调用该方法的方式,因此在cellForItemAtIndexPath中选择单元格是有问题的。最初设置集合视图时,不仅会调用它。当集合视图滚动时,它被连续调用,因为集合视图仅向其数据源询问可见单元,从而节省了大量开销。
由于集合视图不会将其所有单元格都保留在内存中,因此它们需要管理自己单元格的选定状态。他们不希望您向他们提供已设置isSelected属性的单元格。他们希望您为他们提供单元格,并且将在适当的情况下在其上设置选定的属性。
这就是为什么Apple警告您不要直接设置UICollectionViewCell的isSelected属性。 UICollectionView希望为您解决这个问题。
SO ,答案是不尝试在cellForItemAtIndexPath方法中选择单元格。选择要最初选择的单元格的最佳位置是UICollectionViewController的viewWillAppear方法。在该方法中,通过调用UICollectionView.selectItem(at:animated:scrollPosition :)选择所有所需的单元格,然后直接在单元格上选择不要 set 。
答案 12 :(得分:0)
在[UICollectionView selectItemAtIndexPath:animated:scrollPosition:]
中调用 <{em> [UICollectionView collectionView:cellForItemAtIndexPath:]
和dispatch_async(dispatch_get_main_queue(), ^{});
时无效,请尝试在{{1}}内调用它们
块。
这就是最终为我解决的问题。
答案 13 :(得分:0)
Collectionview 选择,取消选择问题已解决。在viewDidLoad
中,添加collViewRiskPreferences.allowsMultipleSelection = false
并添加以下内容
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier:"MyCell", for: indexPath) as? MyCell else { return UICollectionViewCell() }
cell.setupCellStyle(isSelected: false)
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
guard let cell = collectionView.cellForItem(at: indexPath) else { return }
cell.setupCellStyle(isSelected: true)
}
func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
guard let cell = collectionView.cellForItem(at: indexPath) else { return }
cell.setupCellStyle(isSelected: false)
}
和
class MyCell: UICollectionViewCell {
func setupCellStyle(isSelected: Bool) {
if(isSelected) {
self.contentView.backgroundColor = UIColor.blue
} else {
self.contentView.backgroundColor = UIColor.green
}
}
}
答案 14 :(得分:-1)
最好通过设置backgroundView和选定的背景视图来处理单元格选择和取消选择。我建议确保在layoutSubviews方法中正确设置这两个视图的框架(如果您通过IB设置所选视图和背景视图)。
不要忘记设置您的contentView(如果有的话)背景颜色,以便显示正确的背景视图。
不要直接设置单元格的选择(即通过cell.selected = YES),在集合视图中使用为此目的设计的方法。文件清楚地解释了这一点,但我同意这些信息在指南中有些分散。
您不需要直接在collectionView数据源中查看单元格的背景颜色。
另外,作为最后一点,如果要在单元格的类中实现这些,请不要忘记调用[super prepareForReuse]和[super setSelected:selected],因为您可能会阻止单元格的超类进行单元格选择
如果你需要进一步澄清这个问题,请打我。