![](/img/trans.png)
[英]UICollectionView DidDeselectItemAtIndexPath method not called in Swift
[英]UICollectionView - didDeselectItemAtIndexPath not called if cell is selected
我做的第一件事是设置选中的单元格。
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath];
cell.selected = YES;
return cell;
}
并且单元格被成功选中。 如果用户触摸选定的单元格,则应取消选择单元格并调用委托。 但这永远不会发生。
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
NSLog(@"%s", __PRETTY_FUNCTION__);
}
- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath {
NSLog(@"%s", __PRETTY_FUNCTION__);
}
我知道如果我以编程方式设置选择,则不会调用代表。 设置了委托和数据源。
但是,这个委托被调用:
- (BOOL)collectionView:(UICollectionView *)collectionView shouldHighlightItemAtIndexPath:(NSIndexPath *)indexPath {
NSLog(@"%s", __PRETTY_FUNCTION__);
return YES;
}
如果我删除cell.selected = YES
一切正常。 有谁能解释一下这种行为吗?
问题是,单元格被选中,但UICollectionView
。 对UICollectionView
的额外调用解决了这个问题:
[collectionView selectItemAtIndexPath:indexPath animated:NO scrollPosition:UICollectionViewScrollPositionNone];
完整代码:
- (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;
}
我保留这个问题是为了帮助可能面临同样问题的人。
我认为@zeiteisen 提供的解决方案是一种解决方案。 实际的事情在于选择模式。 在属性cell.selected
无需设置任何cell.selected
。
UICollectionView
名称有两个属性allowsMultipleSelection
和allowsSelection
。
默认情况下, allowsMultipleSelection
为NO
, allowsSelection
为YES
。
如果您只想选择一个单元格,那么代码@the 初始化看起来像
yourCollectionView.allowsMultipleSelection = NO;
yourCollectionView.allowsSelection = YES; //this is set by default
然后设置将允许您一次只选择一个单元格,而不是更少。 您必须至少选择一个单元格。 除非您选择另一个单元格,否则不会调用didDeselectItemAtIndexPath
。 点击已选择的UICollectionViewCell
不会使其取消选择。 这是实施背后的政策。
如果要选择多个单元格,则代码@the 初始化应如下所示:
yourCollectionView.allowsMultipleSelection = YES;
yourCollectionView.allowsSelection = YES; //this is set by default
然后设置将允许选择多个单元格。 此设置允许选择一个或多个UICollectionViewCell
。 选定的单元格数将是
0 <= number_selected_cell <= total_number_of_cell
这是多单元选择背后的策略。
如果您打算使用上述任何一种,欢迎您使用 apples api 而不会有额外的麻烦,否则您必须找到一种方法来使用您自己的代码或 apple 的 api 潜入您的目标。
我有同样的问题。 我在加载表格时预先选择了单元格,但我必须双击一个单元格才能取消选择它。 @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
}
将此行添加到您的 didSelectItemAtIndexPath 方法中
[collectionView selectItemAtIndexPath:indexPath animated:NO scrollPosition:nil]
就我而言,我想更改按钮的背景,即集合视图中单元格的背景:
class CustomCVCell: UICollectionViewCell {
override var isSelected: Bool {
didSet {
grayBackgroundViewWithImage.image =
isSelected ? UIImage(named: "") : UIImage()
}
}
在存储集合视图的主类中创建这个变量:
class CustomViewController: UIViewController {
///save the indexPath of last selected cell
private var lastSelectedIndexPath: IndexPath? }
在 viewDidLoad() 中将此值设置为 false:
customCollectionView.allowsMultipleSelection = false
数据源中的进一步代码。 在我的情况下,应该选择第一个单元格:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CustomCVCell.cellID(),
for: indexPath) as! CustomCVCell
if indexPath.row == 0 {
lastSelectedIndexPath = indexPath
cell.isSelected = true
}
//update last select state from lastSelectedIndexPath
cell.isSelected = (lastSelectedIndexPath == indexPath)
return cell
}
委托中的进一步代码:
///UICollectionViewDelegate
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
guard lastSelectedIndexPath != indexPath else { return }
if let index = lastSelectedIndexPath {
let cell = collectionView.cellForItem(at: index) as! CustomCVCell
cell.isSelected = false
}
let cell = collectionView.cellForItem(at: indexPath) as! CustomCVCell
cell.isSelected = true
lastSelectedIndexPath = indexPath
}
重新加载单元格对我来说是解决方案。 我需要的是在短时间内更改单元格中的图像。 我将图像分配给 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])
}
希望它可以帮助某人。
在我的情况下,它是由使用相同的逻辑引起的
func collectionView(_ collectionView: UICollectionView, shouldHighlightItemAt indexPath: IndexPath) -> Bool
至于
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.
希望这会节省某人的时间:)
我遇到了同样的问题,如果你进一步调查,你会发现不仅没有调用 diddiselect,而且触摸本身也没有被单元感知。 为我解决的是允许异步执行选择并手动设置 selecItem 。 在 cellForItemAt 内。
DispatchQueue.main.async {
cell.isSelected = true
collectionView.selectItem(at: indexPath, animated: false, scrollPosition: .init())
}
如果您不想看到动作,请在动画上使用 .init() 和 false。 如果您不使用 async 块包装它,您将在滚动时看到 UI 跳跃。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.