Uicollectionview Selected Cells Issue

UICollectionView cell selection and cell reuse

Your observation is correct. This behavior is happening due to the reuse of cells. But you dont have to do any thing with the prepareForReuse. Instead do your check in cellForItem and set the properties accordingly. Some thing like..

 - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cvCell" forIndexPath:indexPath];

if (cell.selected) {
cell.backgroundColor = [UIColor blueColor]; // highlight selection
}
else
{
cell.backgroundColor = [UIColor redColor]; // Default color
}
return cell;
}

-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {

UICollectionViewCell *datasetCell =[collectionView cellForItemAtIndexPath:indexPath];
datasetCell.backgroundColor = [UIColor blueColor]; // highlight selection
}

-(void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath {

UICollectionViewCell *datasetCell =[collectionView cellForItemAtIndexPath:indexPath];
datasetCell.backgroundColor = [UIColor redColor]; // Default color
}

UICollectionView selected cells issue

I have also worked on same things, I have following solution for that.

You need to create array of indexPath which will store selected indexPath.

var arrSelectedIndexPath = [IndexPath]()

In cellForRowAtItem method add following code which will check if arrSelectedIndexPath contains indexPath then display selected active background else display inactive background.

if arrSelectedIndexPath.contains(indexPath) {
cell?.backgroundView = collectionActive
} else {
cell?.backgroundView = collectionInactive
}

In didSelect method you need to add following code which also same as above logic, but just add or remove indexPath.

if arrSelectedIndexPath.contains(indexPath) {
cell?.backgroundView = collectionInactive
arrSelectedIndexPath.remove(at: arrSelectedIndexPath.index(of: indexPath)!)
} else {
cell?.backgroundView = collectionInactive
arrSelectedIndexPath.append(indexPath)
}

I hope this solution work for you.

UICollectionView issue with Select/Deselect cell

As I understand, you want your collectionView can only select 1 cell at a time and if selected cell is clicked again, it will be deselected. If I'm misunderstanding anything, please tell me.

First

  • You shouldn't change textColor of day in didSelectItemAtIndexPath and didDeselectItemAtIndexPath methods. Because when you scroll collectionView, cells will be reused and color of day will be wrong for some cells.
  • To resolve it, using property selected of UICollectionViewCell.

    SmartCalendarDayCell.m

    - (void)setSelected:(BOOL)selected {
    [super setSelected:selected];

    if (selected) {
    self.day.textColor = [UIColor colorWithHexString:@"#D97E66" setAlpha:1];
    } else {
    self.day.textColor = [UIColor lightGrayColor];
    }
    }

Second

  • To deselect selected cell, you should check and do it on collectionView:shouldSelectItemAtIndexPath: method.

    - (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath {
    if ([collectionView.indexPathsForSelectedItems containsObject:indexPath]) {
    [collectionView deselectItemAtIndexPath:indexPath animated:NO];
    return NO;
    }

    return YES;
    }

For more detail, you can check my demo repo here.

UICollectionView select and deselect

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()
}
}

}

UICollectionView selecting a previously selected cell after reuse

Try this

--cellForItem function

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

if selectedIndexPath == indexPath{
cell.showDimViewAndCheckmark()
selectedCover = notebookCovers[indexPath.row]
saveButton.isEnabled = true
} else {
cell.hideDimViewAndCheckmark()
selectedCover = nil
saveButton.isEnabled = false
}

return cell
}

-- didSelectItemAt function

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

if selectedIndexPath != indexPath || selectedIndexPath == nil {
// Select Cell
selectedIndexPath = indexPath
} else {
// Deselect Cell
selectedIndexPath = nil
}

collectionView.reloadData()
}

UICollectionView is selecting multiple cell even multiple cell selection is false

You should make use of the "isSelected" method for the collection view cell. The way you are doing it is only selecting the cell there is no way of unselecting it. Also, you will need to unselect the previous selected cell If there are any.

So I recommend using this method:

Firstly,

        collectionView.allowsMultipleSelection = false

on the UICollectionViewCell you can override the isSelected method

didSet {
if isSelected {
// Change UI for selected state
radioButton.setImage(#imageLiteral(resourceName: "greenTick"), for: .normal)
} else {
// Chage UI for unselected state
radioButton.setImage(#imageLiteral(resourceName: "radioInactive"), for: .normal)
}
}

Finally when you need to find out the indexpath for the selected item.

            guard let selectedIndex = self.collectionView.indexPathsForSelectedItems?.first else { return }

UICollectionView and Selected Cell loses selection while scrolling

You will need to do some modifications in your logic;

//CollectionViewCell Custom Class
import UIKit

class CollectionViewCell: UICollectionViewCell {

override var selected: Bool {
get {
return super.selected;
}

set {
if (super.selected != newValue) {
super.selected = newValue

let icon = self.viewWithTag(10) as? UIImageView
icon?.image = icon?.image!.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate)

let label = self.viewWithTag(100) as? UILabel

if (newValue == true) {
icon?.tintColor = UIColor.redColor()
label?.textColor = UIColor.redColor()
} else {
icon?.tintColor = UIColor.blackColor()
label?.textColor = UIColor.lightGrayColor()
}
}
}
} //P.E.

}

and then;

//Define a class variable in your viewController
var cellStatus:NSMutableDictionary = NSMutableDictionary();

//Collection view delegate methods
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {

var cell:CollectionViewCell? = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as? CollectionViewCell;

cell!.selected = (cellStatus[indexPath.row] as? Bool) ?? false;

return cell!;
}

func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
//Updating cell status
let cell = collectionView.cellForItemAtIndexPath(indexPath)
cell?.selected = true;

//Updating dic
self.cellStatus[indexPath.row] = true;
}

func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath) {
//Updating cell status
let cell = collectionView.cellForItemAtIndexPath(indexPath)
cell?.selected = false;

//Updating dic
self.cellStatus[indexPath.row] = false;
}

Note: The approach of changing image icon color is not good. it is taking too much processing power which may hang the scrolling. There should be used two separate images for each state.



Related Topics



Leave a reply



Submit