Reputation: 141
Everytime a user click on a specific cell, the cell will have a border. The problem is when I scroll back and forth, the border is selecting random cell to have a border.
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let cell = collectionView.cellForItem(at: indexPath)
cell?.layer.borderColor = UIColor.blue.cgColor
cell?.layer.borderWidth = 1
}
just in case you're looking for the didDeselect part
func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
let cell = collectionView.cellForItem(at: indexPath)
cell?.layer.borderColor = UIColor.clear.cgColor
cell?.layer.borderWidth = 1
}
Upvotes: 6
Views: 17566
Reputation: 711
You can add border easily to selectedCell using "selectedRow".
import UIKit
class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
var selectedRow = -1
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
if selectedRow == indexPath.row {
cell.layer.borderColor = UIColor.blue.cgColor
cell.layer.borderWidth = 1
}
else {
cell.layer.borderWidth = 0
}
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if selectedRow == indexPath.row {
selectedRow = -1
} else {
selectedRow = indexPath.row
}
collectionView.reloadData()
}
}
Upvotes: 6
Reputation: 2154
It is because reusability of cells. You should take property in your cell model to track selected status - isSelected: Bool
Now in cellForItem
method, you have to put if else and make your cell bordered if isSelected
is true
.
Here note that, don't forgot to put else part and remove border in else part.
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let cell = collectionView.cellForItem(at: indexPath)
cell?.layer.borderColor = UIColor.blue.cgColor
cell?.layer.borderWidth = 1
cell?.isSelected = true
}
func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
let cell = collectionView.cellForItem(at: indexPath)
cell?.layer.borderColor = UIColor.clear.cgColor
cell?.layer.borderWidth = 1
cell?.isSelected = false
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath)
...
...
if cell.isSelected {
//put border logic
}else {
// remove border
}
return cell
}
Upvotes: 15
Reputation: 1822
You can use like this my Way:
var selectedIndexPath: NSIndexPath{
didSet{
collectionView.reloadData()
}
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
selectedIndexPath = indexPath
}
func collectionView(_ collectionView: UICollectionView,
cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
var borderColor: CGColor! = UIColor.clear.cgColor
var borderWidth: CGFloat = 0
if indexPath == selectedIndexPath{
borderColor = UIColor.brown.cgColor
borderWidth = 1 //or whatever you please
}else{
borderColor = UIColor.clear.cgColor
borderWidth = 0
}
cell.layer.borderWidth = borderWidth //You can use your component
cell.layer.borderColor = borderColor
}
Upvotes: 2
Reputation: 8516
Because of cell re-use, you are currently facing this issue. To solve this:
When you select a cell (in didSelectItemAt
), save the indexPath.row
in local variable. In cellForRow
method, put check like: if indexPath.row==savedValue, then borderColor will be blue, else normal color.
Upvotes: 0