ios UICollectionView - 如果选择了单元格,则不会调用 didDeselectItemAtIndexPath
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20380512/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
UICollectionView - didDeselectItemAtIndexPath not called if cell is selected
提问by zeiteisen
The first thing I do is to set the cell selected.
我做的第一件事是设置选中的单元格。
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath];
cell.selected = YES;
return cell;
}
And the cell is successfully selected. If the user touches the selected cell, than should the cell be deselected and the delegates be called. But this never happen.
并且单元格被成功选中。如果用户触摸选定的单元格,则应取消选择单元格并调用委托。但这永远不会发生。
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
NSLog(@"%s", __PRETTY_FUNCTION__);
}
- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath {
NSLog(@"%s", __PRETTY_FUNCTION__);
}
I know that the delegates are not called if I set the selection programmatically. The delegate and datasource are set.
我知道如果我以编程方式设置选择,则不会调用代表。设置了委托和数据源。
However, this delegate gets called:
但是,这个委托被调用:
- (BOOL)collectionView:(UICollectionView *)collectionView shouldHighlightItemAtIndexPath:(NSIndexPath *)indexPath {
NSLog(@"%s", __PRETTY_FUNCTION__);
return YES;
}
If I remove the cell.selected = YES
than everything is working. Is there any one who can me explain this behaviour?
如果我删除cell.selected = YES
比一切正常。有谁能解释一下这种行为吗?
回答by zeiteisen
The issue is, that the cell is selected, but the UICollectionView
does not know anything about it. An extra call for the UICollectionView
solves the problem:
问题是,该单元格已被选中,但UICollectionView
它对此一无所知。一个额外的调用UICollectionView
解决了这个问题:
[collectionView selectItemAtIndexPath:indexPath animated:NO scrollPosition:UICollectionViewScrollPositionNone];
Full code:
完整代码:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath];
cell.selected = YES;
[collectionView selectItemAtIndexPath:indexPath animated:NO scrollPosition:UICollectionViewScrollPositionNone];
return cell;
}
I keep the question to help someone who may face the same problem.
我保留这个问题是为了帮助可能面临同样问题的人。
回答by Ratul Sharker
I think the solution @zeiteisen provided is a way around solution. The actual thing lies in the selection mode. There is nothing to be set the in property cell.selected
.
我认为@zeiteisen 提供的解决方案是一种解决方案。实际的事情在于选择模式。无需设置 in 属性cell.selected
。
There are two properties of the UICollectionView
name allowsMultipleSelection
and allowsSelection
.
UICollectionView
nameallowsMultipleSelection
和有两个属性allowsSelection
。
allowsMultipleSelection
is NO
by default and allowsSelection
is YES
.
allowsMultipleSelection
是NO
默认和allowsSelection
是YES
。
If you want to select only one cell then the code @the initialization look like
如果您只想选择一个单元格,那么代码@the 初始化看起来像
yourCollectionView.allowsMultipleSelection = NO;
yourCollectionView.allowsSelection = YES; //this is set by default
Then the settings will allow you select only one cell at a time, not less not more. You must have to select at least one cell.The didDeselectItemAtIndexPath
wont be called unless you select another cell. Tapping an already selected UICollectionViewCell
won't make it to Deselect. This is the policy behind the implementation.
然后设置将允许您一次只选择一个单元格,而不是更少。您必须至少选择一个单元格。该didDeselectItemAtIndexPath
除非您选择另一个单元格不会被调用。点击已选择的UICollectionViewCell
不会使其取消选择。这是实施背后的政策。
If you want to select multiple cell then the code @the initialization should look like the following:
如果要选择多个单元格,则代码@the 初始化应如下所示:
yourCollectionView.allowsMultipleSelection = YES;
yourCollectionView.allowsSelection = YES; //this is set by default
Then the settings will allow to select multiple cell. This settings allow none or multiple UICollectionViewCell
to be selected. Number of cell selected will be
然后设置将允许选择多个单元格。此设置允许选择一个或多个UICollectionViewCell
。选定的单元格数将是
0 <= number_selected_cell <= total_number_of_cell
This is the policy behind the multiple cell selection.
这是多单元选择背后的策略。
If you are intended to use any of the above you are welcome to use apples api without extra headache, otherwise you got to find a way around to sneak into your goal using your own code or apple's api.
如果您打算使用上述任何一种,欢迎您使用 apples api 而不会有额外的麻烦,否则您必须找到一种方法来使用您自己的代码或 apple 的 api 潜入您的目标。
回答by Meagan S.
I had the same issue. I pre-selected cells upon table load yet I had to double tap a cell to deselect it. @zeiteisen answer helped me. However, I'm working in Swift 3 so I thought I'd give an answer in Swift.
我遇到过同样的问题。我在加载表格时预先选择了单元格,但我必须双击一个单元格才能取消选择它。@zeiteisen 的回答帮助了我。但是,我在 Swift 3 中工作,所以我想我会在 Swift 中给出答案。
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! Cell
if /*Test for Selection*/ {
cell.isSelected = true
collectionView.selectItem(at: indexPath, animated: false, scrollPosition: .left)
}
return cell
}
回答by Nupur Sharma
Add this line to your didSelectItemAtIndexPath method
将此行添加到您的 didSelectItemAtIndexPath 方法中
[collectionView selectItemAtIndexPath:indexPath animated:NO scrollPosition:nil]
回答by mra214
In my case it was caused by using same logic for
在我的情况下,它是由使用相同的逻辑引起的
func collectionView(_ collectionView: UICollectionView, shouldHighlightItemAt indexPath: IndexPath) -> Bool
as for
至于
func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool
And when cell was selected shouldHighlightItemAt was returning false - and this prevented me to deselect that cell.
And when cell was selected shouldHighlightItemAt was returning false - and this prevented me to deselect that cell.
Hope this will save someone's time :)
希望这会节省某人的时间:)
回答by TDesign
I was having the same issue, if you investigate further you willl see that not only the diddiselect is not called, but the touch itself is not perceived by the cell. What solved for me was to allow for async execution of the selection and set the selecItem manually as well. Inside cellForItemAt.
我遇到了同样的问题,如果你进一步调查,你会发现不仅没有调用 diddiselect,而且触摸本身也没有被单元感知。为我解决的是允许异步执行选择并手动设置 selecItem 。在 cellForItemAt 内。
DispatchQueue.main.async {
cell.isSelected = true
collectionView.selectItem(at: indexPath, animated: false, scrollPosition: .init())
}
Use .init() and false on animated if you don't want to see movements. If you don't wrap this with the async block you will see the UI jumping while scrolling.
如果您不想看到动作,请在动画上使用 .init() 和 false。如果您不使用 async 块包装它,您将在滚动时看到 UI 跳跃。
回答by ysnzlcn
Reloading the cell was solution for me. What i need was changing image in cell for a brief moment. I assign image to imageView in cellForItemAtIndexPath and when user touches the cell i change image and run mycode then reload the cell.
重新加载单元格对我来说是解决方案。我需要的是在短时间内更改单元格中的图像。我将图像分配给 cellForItemAtIndexPath 中的 imageView,当用户触摸单元格时,我更改图像并运行 mycode,然后重新加载单元格。
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
let cell = collectionView.cellForItemAtIndexPath(indexPath) as! MenuCollectionViewCell
cell.backgroundImageView.image = UIImage(named: "selected")
// handle tap events
collectionView.reloadItemsAtIndexPaths([indexPath])
}
Hope it helps someone.
希望它可以帮助某人。