how to single select cell in collection view..?
This is happening because the collectionView reuse the cells;
you should store the selected cell's IndexPath in a variable:
ObjC :
@property (nonatomic, retain) NSIndexPath *selectedIndexPath;
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell* cell = [collectionView cellForItemAtIndexPath:indexPath];
cell.layer.backgroundColor = [UIColor blackColor].CGColor;
NSLog(@"INDEXPATH:-%ld",(long)indexPath.row);
self.selectedIndexPath = indexPath
}
-(void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath{
UICollectionViewCell* cell = [collectionView cellForItemAtIndexPath:indexPath];
cell.layer.backgroundColor = [UIColor whiteColor].CGColor;
self.selectedIndexPath = nil
}
Swift :
var selectedIndexPath: IndexPath?
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let cell = collectionView.cellForItem(at: indexPath)
cell.layer.backgroundColor = UIColor.black
self.selectedIndexPath = indexPath
}
func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
let cell = collectionView.cellForItem(at: indexPath)
cell.layer.backgroundColor = UIColor.white
self.selectedIndexPath = nil
}
than in "cell for row at indexPath" check :
ObjC :
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell* cell = [collectionView cellForItemAtIndexPath:indexPath];
cell.layer.cornerRadius = cellWidth / 2.0;
if (self.selectedIndexPath != nil && indexPath == self.selectedIndexPath) {
cell.layer.backgroundColor = [UIColor blackColor].CGColor;
else {
cell.layer.backgroundColor = [UIColor whiteColor].CGColor;
}
return cell
}
Swift :
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.cellForItem(at: indexPath)
cell.layer.cornerRadius = cellWidth / 2
if self.selectedIndexPath != nil && indexPath == self.selectedIndexPath {
cell.layer.backgroundColor = UIColor.black
else {
cell.layer.backgroundColor = UIColor.white
}
}
Thanks for Alberto Scampini this code for swift 3.1
var selectedIndexPath: IndexPath?
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = self.collectionView.dequeueReusableCell(withReuseIdentifier: "SegmentChoiceCVCell", for: indexPath) as! SegmentChoiceCVCell
//configure cell
if selectedIndexPath != nil && indexPath == selectedIndexPath {
cell.checkIcon.backgroundColor = UIColor.black
}else{
cell.checkIcon.backgroundColor = UIColor.white
}
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let cell = collectionView.cellForItem(at: indexPath) as! SegmentChoiceCVCell
cell.checkIcon.backgroundColor = UIColor.black
self.selectedIndexPath = indexPath
}
func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
let cell: SegmentChoiceCVCell = collectionView.cellForItem(at: indexPath) as! SegmentChoiceCVCell
cell.checkIcon.backgroundColor = white
selectedIndexPath = nil
}
I know that I am late to the party. I had the same problem. And after looking around in stackoverflow. Here's my solution. It may help starters understand the UICollectionViewCell a bit easier.
"cellForItemAtIndexPath" method controls how the cell will be display. And cells that are off-screen will not be updated.
Swift 4
First, you need to sub-class your cell.
class SubclassedCell: UICollectionViewCell {
@IBOutlet var cellImage: UIImageView!
@IBOutlet var cellCaption: UILabel!
}
extension SubclassedCell{
func highlightEffect(){
self.layer.borderWidth = 3.0
self.layer.borderColor = UIColor.lightGray.cgColor
}
func removeHighlight(){
self.layer.borderColor = UIColor.clear.cgColor
}
}
And now for the "cellForItemAt" method.
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "blahblahblah", for: indexPath) as! SubclassedCell
cell.cellImage.image = yourImages[indexPath.item]
cell.cellCaption.text = yourImageNames[indexPath.item]
cell.removeHighlight() // Call subclassed cell method.
if indexPath.item == selectedItem {
cell.highlightEffect() // Call subclassed cell method.
preSelected = IndexPath(item: indexPath.item, section: indexPath.section)
}
collecttionRef = collectionView
return cell
}
Then, for the "didSelectItemAt" method
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath){
collectionView.allowsMultipleSelection = false
if let cell = collectionView.cellForItem(at: indexPath) as! SubclassedCell?{
let indexPathData = NSKeyedArchiver.archivedData(withRootObject: indexPath)
UserDefaults.standard.set(indexPathData,forKey: "backgroundIndexPath")
//I got some unwrapped crash for my App so I have to use UserDefault to fix the unwrapped problem. You could ignore these both lines.
selectedItem = indexPath.item //selectedItem is used in the "cellForItemAt" method above.
collectionView.reloadData() //update all cells. It could be heavy if you have many cells.
}
}