Home > Mobile >  Select and Deselect in collectionView swift ios
Select and Deselect in collectionView swift ios

Time:06-20

I'm working on collectionView and stuck on like when user tap on collectionView cell item it change the colour accordingly and other item colour also change.First cell item would be active and colour will be blue and other cell colour will be deactive and colour gray.But in my case the code not working fine see code below.

var category: [Category] = [
        Category(cat: "For You"),
        Category(cat: "Top chats"),
        Category(cat: "Kids"),
        Category(cat: "Categories"),
        Category(cat: "Editor Choice")
    ]
    
    var isSelected: Int? = nil {
        didSet {
            DispatchQueue.main.async {
                self.collectionView.reloadData()
            }
        }
    }
extension DashboardViewController: UICollectionViewDelegate {
    
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        self.isSelected = indexPath.row
    }
}

extension DashboardViewController: UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return category.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        configureDashboardCell(collectionView, cellForItemAt: indexPath)
    }
    
    func configureDashboardCell(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: String(describing: CategoryCell.self), for: indexPath) as? CategoryCell else {return UICollectionViewCell()}
        cell.lblName.text = category[indexPath.item].cat
        
        if self.isSelected == indexPath.row {
            let textColor: UIColor = .blue
            let underLineColor: UIColor = .blue
            let underLineStyle = NSUnderlineStyle.single.rawValue
            
            let labelAtributes:[NSMutableAttributedString.Key : Any] = [
                NSAttributedString.Key.foregroundColor: textColor,
                NSAttributedString.Key.underlineStyle: underLineStyle,
                NSAttributedString.Key.underlineColor: underLineColor
            ]
            let underlineAttributedString = NSAttributedString(string: cell.lblName.text ?? "",
                                                        attributes: labelAtributes)
            cell.lblName.attributedText = underlineAttributedString
        } else {
            let textColor: UIColor = .gray
            let labelAtributes:[NSMutableAttributedString.Key : Any] = [
                NSAttributedString.Key.foregroundColor: textColor
            ]
            let underlineAttributedString = NSAttributedString(string: cell.lblName.text ?? "",
                                                attributes: labelAtributes)
            cell.lblName.attributedText = underlineAttributedString
        }
        return cell
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: (self.collectionView.bounds.width / 3) - 5 , height: 40)
    }
}

CodePudding user response:

In my opinion, I would recomment you isSelected property to control all of the style.

// Cells become highlighted when the user touches them. 
// The selected state is toggled when the user lifts up from a highlighted cell.
// Override these methods to provide custom UI for a selected or highlighted state.
// The collection view may call the setters inside an animation block.

open var isSelected: Bool


You should put all the task to cell, rather than directly control it through collectionView.

As you mentioned above,

First cell item would be active and colour will be blue and other cell colour will be deactive and colour gray

so you just want two State, either selected or deselected, and one selected only.

Let we have a try collection.selectItem(at: <#T##IndexPath?#>, animated: <#T##Bool#>, scrollPosition: <#T##UICollectionView.ScrollPosition#>), it make cell call isSelected twice both for new selected Cell and the old one needed to deselect.

CodePudding user response:

Please use your selection in willDisplayCell. First let the cell to be in the view in cellForRowAt and then try to redesign the cell whatever you wish.

func configureDashboardCell(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: String(describing: CategoryCell.self), for: indexPath) as? CategoryCell else {return UICollectionViewCell()}
        cell.lblName.text = category[indexPath.item].cat
        let textColor: UIColor = .gray
            let labelAtributes:[NSMutableAttributedString.Key : Any] = [
                NSAttributedString.Key.foregroundColor: textColor
            ]
            let underlineAttributedString = NSAttributedString(string: cell.lblName.text ?? "",
                                                attributes: labelAtributes)
            cell.lblName.attributedText = underlineAttributedString
        return cell
    }

func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
if self.isSelected == indexPath.row {
            let textColor: UIColor = .blue
            let underLineColor: UIColor = .blue
            let underLineStyle = NSUnderlineStyle.single.rawValue
            
            let labelAtributes:[NSMutableAttributedString.Key : Any] = [
                NSAttributedString.Key.foregroundColor: textColor,
                NSAttributedString.Key.underlineStyle: underLineStyle,
                NSAttributedString.Key.underlineColor: underLineColor
            ]
            let underlineAttributedString = NSAttributedString(string: cell.lblName.text ?? "",
                                                        attributes: labelAtributes)
            cell.lblName.attributedText = underlineAttributedString
        } 

}

and reload data when the cell is tapped

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        self.isSelected = indexPath.row
        collectionView.reloadData()
    }
  • Related