在UICollectionViewController中只选择一个项目

时间:2017-05-26 15:47:48

标签: ios swift uicollectionview

我已经实现了一个UICollectionViewController的子类,它可以水平滚动,我希望它能够只选择一个项目。

当我在当前屏幕上更改所选项目时,它工作正常。但是,例如,如果我在集合的最开头选择一个项目,然后向右滚动并选择另一个项目,则仍然会选择第一个项目。

这是我的CollectionView的当前版本:

class GenresCollectionVC: UICollectionViewController {

    var selectedIndexPath: IndexPath?

    // MARK: UICollectionViewDataSource
    override func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }

    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return MockData.instance.genres.count
    }

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

        cell.genreNameLabel.text = MockData.instance.genres[indexPath.row]
        if selectedIndexPath == indexPath {
            redraw(selectedCell: cell)
        } else {
            redraw(deselectedCell: cell)
        }

        return cell
    }

    // MARK: UICollectionViewDelegate
    override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        guard let cell = collectionView.cellForItem(at: indexPath) as? GenreCollectionViewCell else {
            return
        }
        redraw(selectedCell: cell)
        selectedIndexPath = indexPath
    }

    override func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
        guard let cell = collectionView.cellForItem(at: indexPath) as? GenreCollectionViewCell else {
            return
        }
        redraw(deselectedCell: cell)
        selectedIndexPath = nil
    }

    private func redraw(selectedCell cell: GenreCollectionViewCell
        ) {
        cell.layer.borderWidth = 1.0
        cell.layer.cornerRadius = cell.bounds.height / 2
        cell.layer.borderColor = UIColor.violetNeeoColor.cgColor

        cell.genreNameLabel.textColor = UIColor.violetNeeoColor
    }

    private func redraw(deselectedCell cell: GenreCollectionViewCell) {
        cell.layer.borderWidth = 0.0
        cell.layer.cornerRadius = 0.0

        cell.genreNameLabel.textColor = UIColor.white
    }
}

我做错了什么?

3 个答案:

答案 0 :(得分:6)

GenreCollectionViewCell课程中,覆盖isSelected属性,即

override var isSelected: Bool{
    willSet{
        super.isSelected = newValue
        if newValue
        {
            self.layer.borderWidth = 1.0
            self.layer.cornerRadius = self.bounds.height / 2
            self.layer.borderColor = UIColor.violetNeeoColor.cgColor
            self.genreNameLabel.textColor = UIColor.violetNeeoColor
        }
        else
        {
            self.layer.borderWidth = 0.0
            self.layer.cornerRadius = 0.0
            self.genreNameLabel.textColor = UIColor.white
        }
    }
}

现在,您无需在didSelectItemAt delegate方法中手动选择/取消选择该单元格。 isSelected属性会自动处理它。

答案 1 :(得分:2)

在这种情况下,保存IndexPath然后使用它作为比较的基础对我来说总是最好的选择。

首先定义你的变量:

var _selectedIndexPath : IndexPath? = nil

然后在didSelectItemAtIndexPath

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath){

            if ((_selectedIndexPath) != nil){

                if indexPath.compare(_selectedIndexPath!) == ComparisonResult.orderedSame {

                    //if the user tap the same cell that was selected previously deselect it.

                    _selectedIndexPath = nil;
                }
                else
                {
\                    // save the currently selected indexPath

                    _selectedIndexPath = indexPath

                }
            }
            else{

                // else, savee the indexpath for future reference if we don't have previous selected cell

                _selectedIndexPath = indexPath;
        }

        // and now only reload only the visible cells

            collectionView.reloadItems(at: collectionView.indexPathsForVisibleItems)
        }

最后检查cellForItemAtIndexPath中选定的单元格:

   func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {


        // Demo implementation
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath as IndexPath)

        if _selectedIndexPath == indexPath{

            //If the cell is selected
            cell.isSelected = true
            cell.backgroundColor = UIColor.red
        }
        else{
            // If the cell is not selected
            cell.isSelected=false
            cell.backgroundColor = UIColor.gray


        }
        return cell
    }

答案 2 :(得分:1)

选择新的indexPath

后,手动取消选择单元格
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    guard let cell = collectionView.cellForItem(at: indexPath) as? GenreCollectionViewCell else {
        return
    }
    if selectedIndexPath != indexPath {
        collectionView(collectionView, didDeselectItemAt: selectedIndexPath)
     }
    redraw(selectedCell: cell)
    selectedIndexPath = indexPath
}

显然,每隔一次点击一个单元格就会调用取消选择委托方法。