Sener
Sener

Reputation: 129

UICollectionView select and deselect

I have UICollectionView 2 rows 10+ cells. deselected by default. when I click it becomes selected but when I click again not deselect.

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


   let cell = collectionView.cellForItem(at: indexPath)


    let collectionActive: UIImageView = {
        let image=UIImageView(image: #imageLiteral(resourceName: "collectionActive"))
        image.contentMode = .scaleAspectFill
        return image
    }()

    let collectionInactive: UIImageView = {
        let image=UIImageView(image: #imageLiteral(resourceName: "collectionInactive"))
        image.contentMode = .scaleAspectFill
        return image
    }()


    if cell?.isSelected == true {
        cell?.backgroundView = collectionActive
    }else{
        cell?.backgroundView = collectionInactive
    }

}

how fix that problem?

Upvotes: 3

Views: 10900

Answers (7)

Gerges Eid
Gerges Eid

Reputation: 1075

override var isSelected: Bool{
   didSet{
     if self.isSelected
       {
       //This block will be executed whenever the cell’s selection state is set to true (i.e For the selected cell)
       }
       else
       {
      //This block will be executed whenever the cell’s selection state is set to false (i.e For the rest of the cells)
       }
   }
}

Add this to your cell

Source

Upvotes: 0

Ely
Ely

Reputation: 9121

In iOS 14 and newer, you can set the backgroundConfiguration property of a cell. Once set, all necessary visual effects for selecting and deselecting works automatically. You can use one of the preconfigured configurations, like this:

cell.backgroundConfiguration = .listSidebarCell()

…or create a UIBackgroundConfiguration object from scratch. You can also change a preconfigured configuration before applying.

More info here: https://developer.apple.com/documentation/uikit/uibackgroundconfiguration

Upvotes: 0

frouo
frouo

Reputation: 5223

If the cell is selected, just set cell.isSelected = false in shouldSelectItemAt delegate and in a DispatchQueue.main.async { } block. So the state is actually changed to false (very) soon after the shouldSelectItemAt has been executed.

It may look like a hack but it actually works.

func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool {
  if let cell = collectionView.cellForItem(at: indexPath), cell.isSelected {
    DispatchQueue.main.async { // change the isSelected state on next tick of the ui thread clock
      cell.isSelected = false
      self.collectionView(collectionView, didDeselectItemAt: indexPath)
    }

    return false
  }

  return true
}

Please let me know if you find/know any cons to do this. Thanks 🙏

Upvotes: 0

Jamil Hasnine Tamim
Jamil Hasnine Tamim

Reputation: 4448

For Swift 5 +

in viewDidLoad()

collectionView.allowsMultipleSelection = true

afterword I implemented these methods

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    let cell = collectionView.cellForItem(at: indexPath) as! MovieDetailsDateCollectionViewCell
    cell.toggleSelected()
}

func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
    let cell = collectionView.cellForItem(at: indexPath) as! MovieDetailsDateCollectionViewCell
    cell.toggleSelected()
}

In TableView Cell class

 class MyCell : UICollectionViewCell {

    func toggleSelected ()
       {
        if (isSelected){
            backgroundColor = .red
           }else {
            backgroundColor = .white
           }
       }

}

Upvotes: 4

Vlad
Vlad

Reputation: 1041

If you don't want to enable multiple selection and only want one cell to be selected at a time, you can use the following delegate instead:

If the cell is selected then this deselects all cells, otherwise if the cell is not selected, it selects it as normal.

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

    if cell.isSelected {
        collectionView.selectItem(at: nil, animated: true, scrollPosition: [])
        return false
    }
    return true
}

Upvotes: 2

Francesco Deliro
Francesco Deliro

Reputation: 3939

According to UICollectionView class doc, you can use:

var selectedBackgroundView: UIView? { get set }

You can use this view to give the cell a custom appearance when it is selected. When the cell is selected, this view is layered above the backgroundView and behind the contentView.

In your example in the cellForItem(at indexPath: IndexPath) -> UICollectionViewCell? function you can set:

cell.backgroundView = collectionInactive
cell.selectedBackgroundView = collectionActive

Upvotes: 0

Ferrakkem Bhuiyan
Ferrakkem Bhuiyan

Reputation: 2783

in viewDidLoad()

collectionView.allowsMultipleSelection = true;

afterword I implemented these methods

func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
    let cell = collectionView.cellForItemAtIndexPath(indexPath) as! MyCell
    cell.toggleSelected()
}

func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath) {
    let cell = collectionView.cellForItemAtIndexPath(indexPath) as! MyCell
    cell.toggleSelected()
}

finally in my class

class MyCell : UICollectionViewCell {

    func toggleSelected ()
    {
        if (selected){
            backgroundColor = UIColor.redColor()
        }else {
            backgroundColor = UIColor.whiteColor()
        }
    }

}

Upvotes: 9

Related Questions