【问题标题】:didDeselectItemAt indexPath doesn't triggered when another cell is selected选择另一个单元格时不会触发 didDeselectItemAt indexPath
【发布时间】:2018-01-04 12:01:50
【问题描述】:

我正在尝试实现此功能:在我的应用程序中,如果我在 UICollectionView 中选择了一个单元格,则边框变为蓝色,如果我选择另一个单元格,则应取消选择前一个并且边框应变为透明。我写了一些方法:

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! ChatCell

        /* Set some settings */
        if globalSelected[indexPath.item] {
            cell.circleView.layer.borderColor = UIColor.blue.cgColor
        } else {
            cell.circleView.layer.borderColor = UIColor.clear.cgColor
        }

        return cell
}

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    //Global variable for maintain selection
    global.selectedChatPath = indexPath
    globalSelected[indexPath.item] = true
    collectionView.reloadData()
}

func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
    if indexPath != nilPath {
        globalSelected[indexPath.item] = false
        collectionView.reloadData()
    }
}

nilPath 只是 IndexPath(item: -1, section: 0),但它没有没关系,因为 collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) 甚至没有被调用。我的 CollectionView 有 allowSelection = true 和 allowsMultipleSelection = false 属性。我将不胜感激。

【问题讨论】:

  • 为 CollectionView 添加委托 "collectionView.delegate = self"
  • @Ragul 谢谢!但它已经完成了:我有另一个类,它符合 UICollectionViewDataSource 和 UICollectionViewDelegate 协议,我声明了这个类的一个实例作为我的 UICollectionView 的委托和数据源。此外,第一步工作正常:单击任何单元格后,边框变为蓝色(这意味着代表团工作正常),但是当我单击其他单元格时,它们的边框也变为蓝色,但前一个的边框单元格仍然是蓝色的(我想要透明的)。
  • 只需为每个选择重新加载collectionView
  • @Ragul 在哪些方法中?据我了解,didSelectItemAt 和 DidDeselectItemAt 正在重新加载我的收藏(它们都包含 collectionView.reloadData())
  • 为什么会被调用?你在同一个运行循环中显式地重新加载整个集合视图......当iOS知道它将重新加载整个集合时,它并不愚蠢地执行deselect一行 -无论如何都在同一个循环中查看。

标签: ios swift uicollectionview


【解决方案1】:

如果只应该同时选择一个单元格,我建议将当前选择的索引路径放入实例变量中(nil 表示未选择任何内容)

var selectedIndexPath : IndexPath?

在cellForItemAt根据实例变量设置颜色

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! ChatCell

    /* Set some settings */
    if let selected = selectedIndexPath, selected == indexPath {
        cell.circleView.layer.borderColor = UIColor.blue.cgColor
    } else {
        cell.circleView.layer.borderColor = UIColor.clear.cgColor
    }

    return cell
}

在didSelectItemAt 中仅重新加载先前和新选定的单元格并将selectedIndexPath 设置为新选定的索引路径。这比重新加载整个集合视图更有效。

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    //Global variable for maintain selection

    var cellsToReload = [indexPath]
    if let selected = selectedIndexPath {
        cellsToReload.append(selected)
    }
    selectedIndexPath = indexPath
    collectionView.reloadItems(at: cellsToReload)
}

didDeselectItemAt 仅在您想明确取消选择单元格时才需要。

【讨论】:

    【解决方案2】:

    试试这个

        func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! ChatCell
    
            /* Set some settings */
            if globalSelected[indexPath.item] {
                cell.circleView.layer.borderColor = UIColor.blue.cgColor
                collectionView.selectItemAtIndexPath(indexPath, animated: false, scrollPosition: .None)
            } 
            else {
                cell.circleView.layer.borderColor = UIColor.clear.cgColor
                collectionView.deselectItemAtIndexPath(indexPath, animated: false)
            }
            return cell
           }
    

    【讨论】:

      【解决方案3】:
      func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
          let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellIdentifier, for: indexPath) as! CollectionViewCell
        if selectedIndex == indexPath.item {
          cell.backgroundColor = .blue
        } else {
          cell.backgroundColor = .clear
        }
      }
      

      在 didSelectItemAt 中,

      func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        selectedIndex = indexPath.item
        collectionView.reloadData()
      }
      

      【讨论】:

      • 谢谢!我已经纠正了我的问题(现在它也包含 cellForItemAt 方法)。
      • 你的代码和collectionview都在同一个控制器上?
      【解决方案4】:

      每次选择一个单元格时重新加载您的 UICollectionView,然后更改所需单元格的边框。 当您重新加载数据时,前一个单元格的边框会被移除,之后您可以为所需的单元格添加边框。

      【讨论】:

        【解决方案5】:

        didDeselectItem 在您再次点击所选单元格之前不会被调用。为了在您点击另一个单元格时取消选择之前选择的单元格,您需要将之前选择的单元格在全局变量中的设置设置为didSelectItem 中的false,如下所示:

        func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
            globalSelected[global.selectedChatPath.item] = false //Set the previously selected cell's setting to false
        
            //Global variable for maintain selection
            global.selectedChatPath = indexPath
            globalSelected[indexPath.item] = true
            collectionView.reloadData()
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-01-08
          • 1970-01-01
          • 2015-05-24
          • 1970-01-01
          • 1970-01-01
          • 2018-12-08
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多