UICollectionView选择和取消选择问题
所以我有一个主要的对象,有许多图像与它关联。图像也是一个对象。UICollectionView选择和取消选择问题
说你有一个集合视图控制器,并在控制器,你有
cellForItemAtIndexPath
以及基于主要对象,如果有与它相关我想当前的图像来设置选择为真。但是我希望用户能够随时“取消”当前单元格,以消除它与主要对象的关联。
我发现如果你设置“选择为真” - 如果cellForItemAtIndexPath
中的主对象和图像之间存在关系,取消选择不再是一个选项。
在
didDeselectItemAtIndexPath
和
didSelectItemAtIndexPath
我有一个记录测试,看看他们是否被调用。如果一个单元格被设置为选中 - 下一个被调用,但如果我从来没有设置一个单元格在cellForItemAtIndexPath
中被选中,我可以选择和取消选择所有我想要的。
这是集合视图应该工作的预期方式吗?我阅读了文档,似乎没有谈论这是如此。我将文档解释为表示它以表格视图单元格的方式工作。有几个明显的变化
这也显示了控制器设置正确,并使用相应的委托方法.... hmmmm
我不知道我理解的问题,但选择的状态设置每个单元格并包含单元格内的所有子视图。你不能解释你的意思是“主对象有许多与之相关的图像”。在子视图中关联?或者你的意思是什么样的联系?
这听起来像是一个设计问题。也许你需要一个包含你需要的任何关联对象的UIView子类;该子类可以被设置为内容视图。例如,我在这里做了一个图像,一个描述和一个与图像相关的录音。所有都在子类中定义,然后每个这些子类成为单个单元格的内容视图。
我也使用了一种安排来将相关图像放到包含它们的文件夹中。在此设置下,文件夹和图像每个都有一个子类,并且可以将任一个作为内容视图附加到单元格(这些内容视图以单个实体的形式存储在核心数据中)。
也许你可以进一步解释你的问题?
你有没有看:
- (BOOL)collectionView:(PSTCollectionView *)collectionView shouldDeselectItemAtIndexPath:(NSIndexPath *)indexPath;
请详细写明您的问题,也许我们可以得到它的底部。我刚刚花了一些时间与UICollectionView。
我认为你的问题可以从混乱被制止,如果你设置cell.selected = YES
编程,原因didSelectItemAtIndexPath:
是没有得到所谓的是因为这是只使用时的CollectionView本身负责细胞的选择(例如,通过自来水)。
我有同样的问题,即。在[UICollectionView collectionView:cellForItemAtIndexPath:]
中设置cell.selected = YES
然后不能通过点击选择单元格。
现在的解决方案:我打电话都[UICollectionViewCell setSelected:]
和[UICollectionView selectItemAtIndexPath:animated:scrollPosition:]
在[UICollectionView collectionView:cellForItemAtIndexPath:]
。
奇怪的,它应该是必要的 - 但它的工作原理..它不会导致无限循环与didSelectItemAtIntexPath委托.. – 2013-07-30 09:58:36
有没有人发现,因为这更好的解决办法,提出了?这个解决方案也适用于我,但这可能是一个错误。 – itslittlejohn 2014-02-20 20:32:33
您是SAINT!我告诉你!不确定在ScrollPosition枚举的具体情况,但它的工作。 (Y) – MrOli3000 2014-09-05 11:00:45
您的Cell类中是否有自定义的setSelected
方法?你用那种方法打电话给[super setSelected:selected]
?
我有一个神秘的问题,我正在使用多个选择,一旦他们被选中,我无法取消选择单元格。调用超级方法解决了这个问题。
我无法相信,经过5年的艰难的iOS编程,我错过了如此明显的东西。咄! – Linasses 2013-11-19 12:56:42
这是我的问题! – NickDK 2015-02-20 16:31:32
这可以很容易错过 – 2cupsOfTech 2016-02-25 17:29:55
我有一个取消选择问题UICollectionView
,我发现我不允许在collectionView上进行多重选择。所以当我测试的时候,我总是在同一个单元格上尝试,如果单选是ON,你不能取消已经选择的单元格。
我不得不添加:
myCollectionView.allowsMultipleSelection = YES;
这是正确的答案 – naz 2014-09-30 10:27:04
我想大多数人错过的原因,是因为它没有暴露在IB收集意见,对不对?我已经找到它了,在IB的任何地方都找不到它。 – 2016-12-21 12:12:37
我不知道为什么UICollectionView
是如此凌乱这样比较UITableViewController
... 有几件事情我发现。
多次调用setSelected:
的原因是因为序列方法被调用。该序列与UITextFieldDelegate
方法非常相似。
在collectionView
实际选择单元之前调用方法collectionView:shouldSelectItemAtIndexPath:
,因为它实际上是在询问“它应该被选中”吗?
collectionView:didSelectItemAtIndexPath:
实际上是在collectionView
选择了该单元之后调用的。因此,名称“确实选择了”。
所以这就是你的情况发生了什么(和我的情况,我不得不在这方面搏斗几个小时)。
用户再次触摸选定的单元格以取消选择。调用shouldSelectItemAtIndexPath:
来检查是否应该选择单元格。 collectionView
选择该单元,然后调用didSelectItemAtIndexPath
。无论你在这一点做什么,在单元的selected
属性设置为YES
之后。这就是为什么像cell.selected = !cell.selected
这样的东西不起作用。
TL; DR - 请collectionView
通过调用deselectItemAtIndexPath:animated:
取消选择委托方法collectionView:shouldSelectItemAtIndexPath:
中的单元格,并返回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;
}
}
独特而正确的答案。没有设置collectionView.allowsMultipleSelection = YES; – WINSergey 2016-10-21 08:31:37
这是慈祥的老人,但由于我使用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
它完美!
单元格选择和取消选择最好通过设置backgroundView和选定的背景视图来处理。我建议确保在layoutSubviews方法中正确设置这两个视图的框架(如果您通过IB设置选定视图和背景视图)。
不要忘记设置你的contentView的(如果你有)背景颜色清除,以便正确的背景视图显示。
不要直接设置单元格的选择(即通过cell.selected = YES),请在集合视图中使用为此设计的方法。文件清楚地解释了这一点,尽管我会同意这些指南中的信息有些分散。
您不应该直接在您的collectionView数据源中直接插入单元格的背景颜色。另外,作为最后一点,如果你在单元的类中实现了这些,不要忘记调用[super prepareForReuse]和[super setSelected:selected],因为你可能会阻止单元的超类做单元选择。
如果您需要关于此主题的进一步说明,请打我。
这是我对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()
}
}
}
这可以工作,但我需要更改所选单元格的边框颜色,这在单元类中不起作用。你能提出一些建议吗? – 2016-12-20 13:00:56
@ArpitDhamane这不适用于我,我使用的是Swift 3 Xcode 8.1。我只能在“collectionView:UICollectionView,cellForItemAt indexPath”里面改变单元格样式:“ – user30646 2017-04-22 18:34:45
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
}
}
简单的解决方案,我发现
生活在iOS 9的时代,这里有很多事情要检查。
- 检查你是否有
collectionView.allowsSelection
设置为YES
- 检查你是否有
collectionView.allowsMultipleSelection
设置为YES
(如果你需要的能力)
现在到了风扇部分。 如果您聆听Apple并将其设置为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];
,它应该只是罚款。
”你从哪里得到'pviews'?我得到一个错误:在Xcode 7.2.1上无法识别的命令'pview'.',lldb-340.4.119.1 – 2016-04-25 18:15:03
https://github.com/facebook/chisel – 2016-04-26 07:28:48
'pviews cell'只是'po [cell recursiveDescription]'调用,你可以在任何视图上做lldb console – 2016-04-26 07:31:31
当调用都[UICollectionViewCell setSelected:]
和[UICollectionView selectItemAtIndexPath:animated:scrollPosition:]
在[UICollectionView collectionView:cellForItemAtIndexPath:]
不起作用尝试调用他们dispatch_async(dispatch_get_main_queue(), ^{});
块内。
这就是最终为我解决的问题。
我使用的是自定义单元格子类,对于我来说,我只需要在子类中设置。
有没有人使用过集合视图,在cellForItemAtIndexPath中将选择设置为YES并且能够取消选择该单元格?我已经建立了两个测试项目,两者的工作原理都是一样的。只要在cellForItemAtIndexPath中将selected设置为true,就不会再次调用取消选择。 – bworby 2013-03-12 04:46:44
不,我认为你不能这样做。如果我在cellLForItemAtIndexPath中设置了一个单元格,则该项目的行为与集合视图(即所选背景)的初始显示中所选择的相同。然而,如果我查看[collectionView indexPathsForSelectedItems]的值,我会得到零 - 这表明我不会有通过常规手段取消选择它的方式。 您可能可以设置cell.selected == NO的值,因为我没有尝试过。但是,如果你无法获得所选项目的索引路径,那肯定会使集合视图更难以使用。 – RegularExpression 2013-03-12 05:03:26
这看起来不奇怪吗?我可能会考虑错误,但我可以肯定地看到,允许某些单元格按照选定的方式启动并能够被取消选择的用途很多。 – bworby 2013-03-13 21:55:53