如何在自定义布局集合视图中取消选择不可见单元格?

时间:2017-11-17 06:56:29

标签: ios swift

获取不可见的单元格可能会也可能不会获取单元格,即使索引位置不为空。

总结:我已经尝试在shouldSelectItemAt函数中选择和取消选择逻辑。选择顺利。但是在选择新单元时,需要取消选择先前选择的单元。当我使用自定义集合视图布局时,我怀疑由于单元格的可重用性而出现问题。

代码:

func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool {
if(collectionView == customContentCollectionView){
let cell:MyContentCell = collectionView.cellForItem(at: indexPath)! as! MyCollectionViewController.MyContentCell

// DESELECTION CODE
if(previouslySelectedIndex != nil){
                                    // following line is error prone (executes but may or may not fetch the cell, sometimes deselect sometimes doesnt)
                                    let prevCell = try collectionView.cellForItem(at: previouslySelectedIndex) as? MyCollectionViewController.MyContentCell

                                    // Also tried with this following (executes but fails sometimes, in case not fetching the cell)
                                    //let prevCell = try collectionView.cellForItem(at: previouslySelectedIndex)! as! MyCollectionViewController.MyContentCell

                                    // Tried this one as well, fetching the previously selected cell using datasource, not directly from collection view
                                    // let prevCell = customContentCollectionView.dataSource?.collectionView(collectionView, cellForItemAt: previouslySelectedIndex) as? MyCollectionViewController.MyContentCell

                                    prevCell?.shapeLayer.strokeColor = bubbleBorder.cgColor
                                    prevCell?.shapeLayer.fillColor = bubbleFill.cgColor
                                    prevCell?.shapeLayer.shadowOpacity = 0.0
                                    prevCell?.labelCount.textColor = bubbleBorder
}

// SELECTION CODE HERE GOES PRETTY WELL
...
previouslySelectedIndex = indexPath
}

N.B。 :我正在使用CustomUICollectionViewFlowLayout,我只需要使用shouldSelectItemAt函数。没有其他功能可供选择和取消选择。

1 个答案:

答案 0 :(得分:0)

let prevCell = try collectionView.cellForItem(at: previouslySelectedIndex) as? MyCollectionViewController.MyContentCell 

返回nil,因为如果用户滚动了collectionView单元格可能已经被重用于其他一些indexPath,那么返回nil。

所以你不应该要求来自collectionView的单元格,而应该询问数据源

let cell = self.collectionView?.dataSource?.collectionView(self.collectionView!, cellForItemAt: IndexPath(row: 0, section: 0))

其他方法是在重用之前使用prepareForReuse重置单元状态。 prepareForReuse听起来更合理的解决方案:)

修改

第二个想法虽然上面的代码将返回单元格,更新未加载/重用的单元格的UI将导致不利影响。相反,只有当单元格可用时,您才可以在shouldSelectItemAt更新取消选择的单元格的UI

func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool {
        if(collectionView == customContentCollectionView){
            let cell:MyContentCell = collectionView.cellForItem(at: indexPath)! as! MyCollectionViewController.MyContentCell

            // DESELECTION CODE
            if(previouslySelectedIndex != nil){
                // following line is error prone (executes but may or may not fetch the cell, sometimes deselect sometimes doesnt)
                if let prevCell = try collectionView.cellForItem(at: previouslySelectedIndex) as? MyCollectionViewController.MyContentCell {

                    // Also tried with this following (executes but fails sometimes, in case not fetching the cell)
                    //let prevCell = try collectionView.cellForItem(at: previouslySelectedIndex)! as! MyCollectionViewController.MyContentCell

                    // Tried this one as well, fetching the previously selected cell using datasource, not directly from collection view
                    // let prevCell = customContentCollectionView.dataSource?.collectionView(collectionView, cellForItemAt: previouslySelectedIndex) as? MyCollectionViewController.MyContentCell

                    prevCell?.shapeLayer.strokeColor = bubbleBorder.cgColor
                    prevCell?.shapeLayer.fillColor = bubbleFill.cgColor
                    prevCell?.shapeLayer.shadowOpacity = 0.0
                    prevCell?.labelCount.textColor = bubbleBorder
                }
            }

            // SELECTION CODE HERE GOES PRETTY WELL
                previouslySelectedIndex = indexPath
        }
    }

如果在上面添加,则应注意确保更新单元格的UI,以便仅在可用时才取消选择。

现在在单元格中实现prepareForReuse

override func prepareForReuse() {
    //reset all the fields of cell
    self.shapeLayer.strokeColor = bubbleBorder.cgColor
    self.shapeLayer.fillColor = bubbleFill.cgColor
    self.shapeLayer.shadowOpacity = 0.0
    self.labelCount.textColor = bubbleBorder
}

最后在cellForItemAtIndexPath

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
     //your code to create cell n all

     if(indexPath == previouslySelectedIndex) {
         //your code to select the cell
     }

     return cell
 }

希望这有帮助