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
Cell will dequeueReusableCell after it disapear from scrollview, so u should
set the bool value to reduction.
You need to maintain press action inside "movieObj". Because the cell is always reusable.