skip to Main Content

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)
    }
}

2

Answers


  1. 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()
        }
    
    Login or Signup to reply.
  2. 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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search