在第二次点击时取消选择 UICollectionView 单元格
Posted
技术标签:
【中文标题】在第二次点击时取消选择 UICollectionView 单元格【英文标题】:Deselect UICollectionView cell on second tap 【发布时间】:2017-12-13 13:54:18 【问题描述】:我的项目应用程序中有 tableViews 和 collectionViews。在表格和集合中,我希望在第一次点击时选择行/单元格,并在第二次点击时取消选择。
通过tableView,我找到了一个相当简单明了的解决方案here,效果很好。
另一方面,CollectionView 被证明是完全不同类型的野兽。与 tableView 不同的是,没有willSelectItemAt
委托方法,因此无法在第二次点击注册之前检查项目是否处于选中状态。实现 shouldDeselectItemAt
和 didDeselectItemAt
不会产生任何结果 - 这些方法永远不会在点击时已被选中的单元格上调用。
唯一可行的solution 建议为每个collectionView 单元格创建一个UIButton
,但它真的应该那么复杂吗?
【问题讨论】:
【参考方案1】:尝试使用“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 true
return false
【讨论】:
谢谢,很好的解决方案!对于else
语句,我使用return true
而不是selectItem()
,因为我需要在didSelectItemAt()
方法中完成一些逻辑,现在它可以按预期完成工作)【参考方案2】:
@pkorosecanswer 的较短版本,具有完全相同的效果,如下所示:
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
【讨论】:
谢谢。这是另一种情况,如果不想向集合视图询问单元格:collectionView.indexPathsForSelectedItems?.contains(indexPath) == true
。【参考方案3】:
我个人认为更简洁的另一个选项是允许在集合视图上进行多项选择,然后在下一次选择之前手动取消选择当前选择的项目。
第一步:允许多选
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
【讨论】:
【参考方案4】:如果您不想多选,请尝试使用此代码进行取消选择。
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
【讨论】:
【参考方案5】:发布类似的解决方案,但调用委托,以便您保持一切同步,模拟实际取消选择(加上稍微清晰的命名):
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
【讨论】:
以上是关于在第二次点击时取消选择 UICollectionView 单元格的主要内容,如果未能解决你的问题,请参考以下文章
UIImagePickerController 在第二次取消时崩溃