在第二次点击时取消选择UICollectionView单元格

时间:2017-12-13 13:54:19

标签: swift uicollectionview

我的项目应用程序中有tableViews和collectionViews。在表和集合中,我希望在第一次点击时选择行/单元格,并在第二次点击时取消选择。

使用tableView,我发现了一个相当简单易用的解决方案here,效果很好。

另一方面,

CollectionView是一种完全不同类型的野兽。与tableView不同,没有willSelectItemAt委托方法,因此在注册第二次点击之前无法检查项目是否处于选定状态。实现shouldDeselectItemAtdidDeselectItemAt不会产生任何结果 - 这些方法永远不会在点击时已经选中的单元格上调用。

唯一合理的solution建议为每个collectionView单元创建一个UIButton,但是它真的应该那么复杂吗?

5 个答案:

答案 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
}