我的项目应用程序中有tableViews和collectionViews。在表和集合中,我希望在第一次点击时选择行/单元格,并在第二次点击时取消选择。
使用tableView,我发现了一个相当简单易用的解决方案here,效果很好。
另一方面, CollectionView是一种完全不同类型的野兽。与tableView不同,没有willSelectItemAt
委托方法,因此在注册第二次点击之前无法检查项目是否处于选定状态。实现shouldDeselectItemAt
和didDeselectItemAt
不会产生任何结果 - 这些方法永远不会在点击时已经选中的单元格上调用。
唯一合理的solution建议为每个collectionView单元创建一个UIButton
,但是它真的应该那么复杂吗?
答案 0 :(得分:11)
尝试使用“shouldSelectItem”UIColllectionViewDelegate方法。
func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool {
let item = collectionView.cellForItem(at: indexPath)
if item?.isSelected ?? false {
collectionView.deselectItem(at: indexPath, animated: true)
} else {
collectionView.selectItem(at: indexPath, animated: true, scrollPosition: [])
}
return false
}
答案 1 :(得分:4)
@pkorosec answer的较短版本具有完全相同的效果,如下所示:
override func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool {
if collectionView.cellForItem(at: indexPath)?.isSelected ?? false {
collectionView.deselectItem(at: indexPath, animated: true)
return false
}
return true
}
@Manav建议的另一种选择是:
override func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool {
if collectionView.indexPathsForSelectedItems?.contains(indexPath) ?? false {
collectionView.deselectItem(at: indexPath, animated: true)
return false
}
return true
}
答案 2 :(得分:0)
我个人认为更干净的另一种选择是允许在集合视图上进行多项选择,然后在下次选择之前手动取消选择当前选择的项目。
第一步:允许多项选择
override func viewDidLoad() {
super.viewDidLoad()
collectionView.allowsMultipleSelection = true
}
第二步:手动取消选择先前选择的项目
func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool {
collectionView.indexPathsForSelectedItems?.forEach { ip in
collectionView.deselectItem(at: ip, animated: true)
}
return true
}
答案 3 :(得分:0)
如果您不想多项选择,请尝试使用此代码取消选择。
var selectedIndex:Int?
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let cell = collectionView.cellForItem(at: indexPath) as! CategoryCollectionViewCell
if selectedIndex == indexPath.row {
selectedIndex = nil
// unselect code here
} else {
selectedIndex = indexPath.row
// Select code here
}
}
func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
// unselect code here
}
答案 4 :(得分:0)
发布一个类似的解决方案,但调用委托,因此您保持所有内容同步,模拟实际取消选择(加上稍微清晰的命名):
func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool {
let isSelectedAlready = collectionView.indexPathsForSelectedItems?.contains(indexPath)
if isSelectedAlready == true {
collectionView.deselectItem(at: indexPath, animated: true)
collectionView.delegate?.collectionView?(collectionView, didDeselectItemAt: indexPath)
return false
}
return true
}