Reputation: 129
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
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
Upvotes: 0
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
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
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
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
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
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