Home > Software design >  CollectionView method didDeselectItemAt not work
CollectionView method didDeselectItemAt not work

Time:05-17

I have a trouble with method "didDeselectItemAt" in collection view. App: i have a collection with cells(see screenshot). User can to highlight only one cell.

when the user clicks on one cell, it is highlighted. when he click on another one, another one is selected, and the previous one becomes normal.

and when I select, for example, the first cell, and then the last one, the first one remains selected. empirically, I found out that this problem. happens when, after the first one, I click on a cell that is out of view while clicking on the first one (you need to scroll)

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    if collectionView == albumsCollectionView {
        guard let cell = collectionView.cellForItem(at: indexPath) as? AlbumCollectionCell else { return }
        cell.isCellSelected()
        presenter?.didChooseAlbum(with: indexPath.row) {
            self.picturesCollectionView.reloadData()
        }}

func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
    if collectionView == albumsCollectionView {
        guard let cell = collectionView.cellForItem(at: indexPath) as? AlbumCollectionCell else { return }
        cell.isCellDeselected()
    }
}

enter image description here

CodePudding user response:

Try with UITapGestureRecognizer, in cellForItemAt add gesture to cell contentView:

let gesture = UITapGestureRecognizer(target: self, action: #selector(self.isCellDeselected))
cell.contentView.addGestureRecognizer(gesture)

add your tapGesture func

@objc func isCellDeselected() {
    print("This Is your cell")
}

CodePudding user response:

As @DonMag mentioned in the comment, you have to track selected state in your data source. Here are the steps.

As you are showing some data in cell, you can make a model for it.

struct Album {
    let name: String
    var isSelected: Bool
}

In AlbumCollectionCell add Album type variable. And override the isSelected property of UICollectionViewCell

class AlbumCollectionCell: UICollectionViewCell {

    var album: Album? {
        didSet {
            guard let shoe = shoe else { return }

            self.shoeSize?.text = shoe.size

            if shoe.isSelected {
                self.backgroundColor = UIColor.orange
            }
            else {
                self.backgroundColor = UIColor.green
            }
            
           self.albumLabel.textColor = .white
           self.albumLabel.text = album.name
        }
    }
    
    override var isSelected: Bool {
        didSet {
            if self.isSelected {
                self.backgroundColor = UIColor.orange
            }
            else {
                self.backgroundColor = UIColor.green
            }
        }
    }
}

In UIViewController, create an array of Album type which holds the data of cells. You may assign the data in viewDidLoad() method.

var albums = [Album]()

Set allowsSelection property of UICollectionView to true.

collectionView.allowsSelection = true

In cellForItem method pass the Album data to cell.

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "AlbumCollectionCell", for: indexPath) as? AlbumCollectionCell {
        cell.album = albums[indexPath.item]
        return cell
    }
    return UICollectionViewCell()
}

Modify didSelectItem method like below.

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    albums[indexPath.item].isSelected = true
}

And override didDeselectItemAt method.

func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
    albums[indexPath.item].isSelected = false
}
  • Related