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
ofday
indidSelectItemAtIndexPath
anddidDeselectItemAtIndexPath
methods. Because when you scrollcollectionView
, cells will be reused and color ofday
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
Bleed Through from Nsbutton Checkbox on Non-Transparent Nspopover
Trouble Passing Array Through Prepareforsegue
How to Use Protocols for Stucts to Emulate Classes Inheritance
How to Show Two Row of Text in a Menu Bar App in MAC Os
Showing Action Sheet in The Custom Cell in Swift
Higlight Speech Utterance in Swiftui
Swift Custom Response Serializer Is Returning Images at Random
How to Get Data to Return from Nsurlsessiondatatask in Swift
Use Tableviewcontroller Inside Skscene
Thread Safety of Method Calls on "Shared" Static Constant Property
Having Trouble with Musickit Sample App Provided by Apple
External Library Usage in Xcode
How to Remove Items from an Array When Deselecting a Row in a UItableview
How to Move an Object Towards a Direction Without Stopping
Firebase Remove Snapshot Children Swift
Touch Sprite, Make It Jump Up Then Fall Down Again(Repeat as Many Times as Spritenode Is Tapped.)