Skip to content

Instantly share code, notes, and snippets.

@Lancewer
Last active May 17, 2023 09:05
Show Gist options
  • Save Lancewer/83f8ea7c3c3e6c82f28799f4888bd134 to your computer and use it in GitHub Desktop.
Save Lancewer/83f8ea7c3c3e6c82f28799f4888bd134 to your computer and use it in GitHub Desktop.
[Collection Single Selection] single selection in UICollectionView with swift #swift #UICollectionView #selection #select #single select
UICollectionView单选cell的解决方法
解决了:
1. 单选时改变cell状态
2. 单选状态的保存,避免cell重用时状态乱跳的问题
//custom cell class
import UIKit
class CollectionViewCell: UICollectionViewCell {
@IBOutlet weak var nameLabel: UILabel!
override var isSelected: Bool{
didSet(newValue){
contentView.backgroundColor = newValue ? UIColor.green : UIColor.white
}
}
}
import UIKit
class ViewController: UIViewController {
//save the indexPath of last selected cell
var lastSelectedIndexPath:IndexPath?
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
extension ViewController: UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
//if selected item is equal to current selected item, ignore it
guard lastSelectedIndexPath != indexPath else {
return
}
if lastSelectedIndexPath != nil {
collectionView.deselectItem(at: lastSelectedIndexPath!, animated: false)
}
print("Selected:\(indexPath)")
let selectedCell = collectionView.cellForItem(at: indexPath) as! CollectionViewCell
selectedCell.isSelected = true
lastSelectedIndexPath = indexPath
}
}
extension ViewController: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 20
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 10
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! CollectionViewCell
cell.nameLabel.text = "S\(indexPath.section)-R\(indexPath.row)"
//update last select state from lastSelectedIndexPath
cell.isSelected = (lastSelectedIndexPath == indexPath)
return cell
}
}
@vidalbenjoe
Copy link

Not working

@SomuYadav
Copy link

SomuYadav commented Feb 20, 2021

 override func viewDidLoad() { 
   collectionView.allowsMultipleSelection = false
 }

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
     guard lastIndex != indexPath else { return }

     if let index = lastIndex {
        let cell = collectionView.cellForItem(at: index) as? YourCell
        cell?.isSelected = false
      }
      
      let cell = collectionView.cellForItem(at: indexPath) as? YourCell
      cell?.isSelected = true
      lastIndex = indexPath
}


@paulmaxgithub
Copy link

paulmaxgithub commented Apr 19, 2021

This works 100%!!!

`In my case, I want to change the background of the button in other words the background of the cell in the collection view:

class CustomCVCell: UICollectionViewCell {

override var isSelected: Bool {
        didSet {
            grayBackgroundViewWithImage.image =
                isSelected ? UIImage(named: "") : UIImage()
        }
    }

In the main class where the collection view is stored create this variable:

class CustomViewController: UIViewController {

///save the indexPath of last selected cell
private var lastSelectedIndexPath: IndexPath? }

In viewDidLoad() set this value to false:

customCollectionView.allowsMultipleSelection = false

Further code in data source. In my case, the first cell should be is selected:

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CustomCVCell.cellID(),
                                                  for: indexPath) as! CustomCVCell
    
    if indexPath.row == 0 {
        lastSelectedIndexPath = indexPath
        cell.isSelected = true
    }
    
    //update last select state from lastSelectedIndexPath
    cell.isSelected = (lastSelectedIndexPath == indexPath)
    
    return cell
}

Further code in the delegate:

///UICollectionViewDelegate
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    guard lastSelectedIndexPath != indexPath else { return }

         if let index = lastSelectedIndexPath {
            let cell = collectionView.cellForItem(at: index) as! CustomCVCell
            cell.isSelected = false
          }

          let cell = collectionView.cellForItem(at: indexPath) as! CustomCVCell
          cell.isSelected = true
    lastSelectedIndexPath = indexPath
}

Screenshot 2021-04-19 at 14 38 16

Screenshot 2021-04-19 at 14 38 22

Screenshot 2021-04-19 at 14 38 32

Screenshot 2021-04-19 at 14 38 37

`

@Nitinbond
Copy link

Nitinbond commented May 17, 2023

For constant index if scrolling.

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

if indexPath.row == 0 && lastSelectedIndexPath == nil {
            lastSelectedIndexPath = indexPath
            cell?.isSelected = true
        } else {
            cell?.isSelected = (lastSelectedIndexPath == indexPath)
}
return cell

}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment