jay123456
jay123456

Reputation: 141

Adding borders on collectionView cell

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

Answers (4)

Kamani Jasmin
Kamani Jasmin

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

Sharad Paghadal
Sharad Paghadal

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

Abhirajsinh Thakore
Abhirajsinh Thakore

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

pkc
pkc

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

Related Questions