skip to Main Content

I have a collection view cell which loads images. On each cell I allow users to long press which pops up buttons with icons which can allow users to click on. Upon clicking on the buttons I show the type of icon they clicked on as a form of rating. My issue now is currently if I scroll down and comes up to the top the button on the image which I displayed after the user has clicked is no longer there. How do I keep the icons stacked to the image even if I scroll

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reUseMoviesCellID, for: indexPath) as! MoviesCollectionCell
        
        cell.btnSmallGoodRate.id = self.movieObj[indexPath.row].id ?? ""
        cell.btnSmallOkRate.id = self.movieObj[indexPath.row].id ?? ""
        cell.btnSmallHateRate.id = self.movieObj[indexPath.row].id ?? ""
        cell.btnSmallLoveRate.id = self.movieObj[indexPath.row].id ?? ""
        cell.tapHandler = {
            Commons.userGlobalRate += 1
            self.lblRated.text = "(Commons.userGlobalRate) rated"
            self.ratedView.backgroundColor = .ratedGoldColour
             if Commons.progressBarValue < 1 {
                  Commons.progressBarValue += 0.2
                  self.ratedTrackBarView.setProgress(Commons.progressBarValue, animated: true)
             }
        }
        
         cell.configure(with: movieObj[indexPath.row])
        let ids = ["id" : movieObj[indexPath.row].id!]
         excludedDictionary.append(ids)
        return cell
    }

class MoviesCollectionCell: UICollectionViewCell {
    
    var tapHandler: (()->())?
    
    let movieImage: UIImageView = {
        let image = UIImageView()
        image.translatesAutoresizingMaskIntoConstraints = false
        image.clipsToBounds = true
        image.contentMode = .scaleAspectFill
        image.layer.cornerRadius = 10
        return image
    }()
    
    let movieOverlay: UIView = {
        let view = UIView()
        view.translatesAutoresizingMaskIntoConstraints = false
        view.backgroundColor = .black.withAlphaComponent(0.3)
        view.alpha = 0
        return view
    }()
    
    let btnRate: UIImageView = {
        let image = UIImageView()
        image.translatesAutoresizingMaskIntoConstraints = false
        image.clipsToBounds = true
        image.contentMode = .scaleAspectFit
        image.alpha = 0
        return image
    }()
    
    let btnSmallGoodRate: ButtonRating = {
        let btn = ButtonRating()
        btn.translatesAutoresizingMaskIntoConstraints = false
        btn.setImage(UIImage(named: "goodRate"), for: .normal)
        btn.addTarget(self, action: #selector(goodItem(_:)), for: .touchUpInside)
         btn.backgroundColor = .black.withAlphaComponent(0.4)
         btn.layer.cornerRadius = 30
        btn.alpha = 0
        return btn
    }()
    
    let removeOverlay: UIButton = {
        let btn = UIButton()
        btn.translatesAutoresizingMaskIntoConstraints = false
        btn.setImage(UIImage(systemName: "xmark"), for: .normal)
        btn.tintColor = .black
        btn.contentMode = .scaleAspectFit
        btn.backgroundColor = .white.withAlphaComponent(0.7)
        btn.layer.cornerRadius = 10
        btn.contentEdgeInsets = UIEdgeInsets(top: 4, left: 4, bottom: 4, right: 4)
        btn.addTarget(self, action: #selector(dismissOverlay), for: .touchUpInside)
        btn.alpha = 0
        return btn
    }()
    
    let btnSmallHateRate: ButtonRating = {
        let btn = ButtonRating()
        btn.translatesAutoresizingMaskIntoConstraints = false
        btn.clipsToBounds = true
        btn.contentMode = .scaleAspectFit
        btn.setImage(UIImage(named: "HateIt"), for: .normal)
        btn.alpha = 0
        btn.addTarget(self, action: #selector(hateItem(_:)), for: .touchUpInside)
         btn.backgroundColor = .black.withAlphaComponent(0.4)
         btn.layer.cornerRadius = 30
        return btn
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        contentView.addSubview(movieImage)
        movieImage.addSubview(btnRate)
        movieImage.addSubview(movieOverlay)
        contentView.addSubview(btnSmallGoodRate)
        contentView.addSubview(btnSmallHateRate)
        contentView.addSubview(removeOverlay)
        
        let directFullPreviewer = UILongPressGestureRecognizer(target: self, action: #selector(directFullPreviewLongPressAction))
        addGestureRecognizer(directFullPreviewer)
        
        btnRate.tintColor = .white
        btnRate.layer.shadowColor = UIColor.black.cgColor
        btnRate.layer.shadowOffset = CGSize(width: 1.0, height: 2.0)
        btnRate.layer.shadowRadius = 2
        btnRate.layer.shadowOpacity = 0.8
        btnRate.layer.masksToBounds = false
    }
    
    override func prepareForReuse() {
        super.prepareForReuse()
        movieImage.image = nil
        btnRate.image = nil
    }
    
    func configure(with res: Responder){

         movieImage.sd_setImage(with: URL(string: res.packShot?.thumbnail ?? ""), placeholderImage: UIImage(named: "ImagePlaceholder"))
         
        
    }
    
    @objc func directFullPreviewLongPressAction(g: UILongPressGestureRecognizer)
    {
        if g.state == UIGestureRecognizer.State.began
        {
            movieOverlay.alpha = 1
            btnSmallGoodRate.alpha = 1
            btnSmallHateRate.alpha = 1
            removeOverlay.alpha = 1
            btnHidden.alpha = 1
        }
    }
    
    @objc func dismissOverlay(){
        movieOverlay.alpha = 0
        btnSmallHateRate.alpha = 0
        btnSmallGoodRate.alpha = 0
        removeOverlay.alpha = 0
         btnHidden.alpha = 0
    }
    
    @objc func hateItem(_ sender: UIButton){
        guard let gestureVariable = sender as? ButtonRating else{
            return
        }
        let movieID = gestureVariable.id
        print("Hate movie ID ", movieID)
        btnSmallOkRate.alpha = 0
        btnSmallHateRate.alpha = 0
        btnSmallGoodRate.alpha = 0
        btnSmallLoveRate.alpha = 0
        removeOverlay.alpha = 0
        btnRate.alpha = 1
        btnRate.image = UIImage(named: "HateIt")
        tapHandler?()
        
    }
    
    @objc func goodItem(_ sender: UIButton){
        guard let gestureVariable = sender as? ButtonRating else{
            return
        }
        let movieID = gestureVariable.id
        print("Good movie ID ", movieID)
        btnSmallOkRate.alpha = 0
        btnSmallHateRate.alpha = 0
        btnSmallGoodRate.alpha = 0
        btnSmallLoveRate.alpha = 0
        removeOverlay.alpha = 0
        btnRate.alpha = 1
        btnRate.image = UIImage(named: "goodRate")
        tapHandler?()
    }
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
}

2

Answers


  1. Cell will dequeueReusableCell after it disapear from scrollview, so u should
    set the bool value to reduction.

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reUseMoviesCellID, for: indexPath) as! MoviesCollectionCell
        
        cell.btnSmallGoodRate.id = self.movieObj[indexPath.row].id ?? ""
        cell.btnSmallOkRate.id = self.movieObj[indexPath.row].id ?? ""
        cell.btnSmallHateRate.id = self.movieObj[indexPath.row].id ?? ""
        cell.btnSmallLoveRate.id = self.movieObj[indexPath.row].id ?? ""
        cell.tapHandler = {
    
            cell.isTap = true
            Commons.userGlobalRate += 1
            self.lblRated.text = "(Commons.userGlobalRate) rated"
            self.ratedView.backgroundColor = .ratedGoldColour
             if Commons.progressBarValue < 1 {
                  Commons.progressBarValue += 0.2
                  self.ratedTrackBarView.setProgress(Commons.progressBarValue, animated: true)
             }
        }
        if cell.isTap{
            self.lblRated.text = "(Commons.userGlobalRate) rated"
            self.ratedView.backgroundColor = .ratedGoldColour
             if Commons.progressBarValue < 1 {
                  Commons.progressBarValue += 0.2
                  self.ratedTrackBarView.setProgress(Commons.progressBarValue, animated: true)
             }
        }
        
         cell.configure(with: movieObj[indexPath.row])
        let ids = ["id" : movieObj[indexPath.row].id!]
         excludedDictionary.append(ids)
        return cell
    }
    
    class MoviesCollectionCell: UICollectionViewCell {
    
      var tapHandler: (()->())?
      var isTap = false
    }
    
    Login or Signup to reply.
  2. You need to maintain press action inside "movieObj". Because the cell is always reusable.

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
            
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reUseMoviesCellID, for: indexPath) as! MoviesCollectionCell
        cell.btnSmallGoodRate.id = self.movieObj[indexPath.row].id ?? ""
        cell.btnSmallOkRate.id = self.movieObj[indexPath.row].id ?? ""
        cell.btnSmallHateRate.id = self.movieObj[indexPath.row].id ?? ""
        cell.btnSmallLoveRate.id = self.movieObj[indexPath.row].id ?? ""
    
        cell.tapHandler = {
            
             movieObj[indexPath.row].isTapped = true
             Commons.userGlobalRate += 1
             self.lblRated.text = "(Commons.userGlobalRate) rated"
             self.ratedView.backgroundColor = .ratedGoldColour
             if Commons.progressBarValue < 1 {
                 Commons.progressBarValue += 0.2
                 self.ratedTrackBarView.setProgress(Commons.progressBarValue, animated: true)
             }
        }
    
        if movieObj[indexPath.row].isTapped {
            
             self.lblRated.text = "(Commons.userGlobalRate) rated"
             self.ratedView.backgroundColor = .ratedGoldColour
             if Commons.progressBarValue < 1 {
    
                Commons.progressBarValue += 0.2
                self.ratedTrackBarView.setProgress(Commons.progressBarValue, animated: true)
              }
         }
     }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search