I have a list of images displaying in a UICollectionViewCell. Now I want a way to display an overlay on the image when user long press on the cell. I have been able to place a long press gesture on the cell but unfortunately how to perform the overlay on the cell is where I'm struggling to achieve.
In my cellForItemAt I have this
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reUseMyCellID, for: indexPath) as! MyCollectionCell
cell.gestureRecognizers?.removeAll()
cell.tag = indexPath.row
let directFullPreviewer = UILongPressGestureRecognizer(target: MyCollectionCell(), action: #selector(MyCollectionCell().directFullPreviewLongPressAction))
cell.addGestureRecognizer(directFullPreviewer)
I have this function for the action on LongPressGestureRecognizer in my MyCollectionCell
class MyCollectionCell: UICollectionViewCell {
weak var textLabel: UILabel!
let movieImage: UIImageView = {
let image = UIImageView()
image.translatesAutoresizingMaskIntoConstraints = false
image.clipsToBounds = true
image.contentMode = .scaleAspectFill
image.layer.cornerRadius = 10
// image.image = UIImage(named: "105")
return image
}()
let movieOverlay: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = .black.withAlphaComponent(0.7)
view.alpha = 0
return view
}()
override init(frame: CGRect) {
super.init(frame: frame)
contentView.addSubview(movieImage)
movieImage.addSubview(btnRate)
movieImage.addSubview(movieOverlay)
NSLayoutConstraint.activate([
movieImage.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 10),
movieImage.topAnchor.constraint(equalTo: contentView.topAnchor),
movieImage.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -10),
movieImage.bottomAnchor.constraint(equalTo: contentView.bottomAnchor),
movieOverlay.leadingAnchor.constraint(equalTo: movieImage.leadingAnchor),
movieOverlay.topAnchor.constraint(equalTo: movieImage.topAnchor),
movieOverlay.trailingAnchor.constraint(equalTo: movieImage.trailingAnchor),
movieOverlay.bottomAnchor.constraint(equalTo: movieImage.bottomAnchor)
])
}
override func prepareForReuse() {
super.prepareForReuse()
movieImage.image = nil
}
func configure(with urlString: String){
movieImage.sd_setImage(with: URL(string: urlString), placeholderImage: UIImage(named: "ImagePlaceholder"))
}
@objc func directFullPreviewLongPressAction(g: UILongPressGestureRecognizer)
{
if g.state == UIGestureRecognizer.State.began
{
movieOverlay.alpha = 1
}
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Your current code has many issues when creating the long press gesture.
You are setting the target to a new cell instance that is immediately thrown away. Set the target as cell
, not MyCollectionCell()
.
You are also using the wrong syntax for the selector. Don't attempt to create a new instance of a cell. Just pass the name of the method #selector(MyCollectionCell.directFullPreviewLongPressAction)
.
Having said all of that, there is no reason this code should be in the cellForItemAt
method. You should be creating the long press gesture inside the cell class.
Remove these three lines from cellForItemAt
:
cell.gestureRecognizers?.removeAll()
let directFullPreviewer = UILongPressGestureRecognizer(target: MyCollectionCell(), action: #selector(MyCollectionCell().directFullPreviewLongPressAction))
cell.addGestureRecognizer(directFullPreviewer)
Then add the following lines inside the init
of MyCollectionCell
:
let directFullPreviewer = UILongPressGestureRecognizer(target: self, action: #selector(directFullPreviewLongPressAction))
addGestureRecognizer(directFullPreviewer)
Now the cell is fully responsible for setting up and handling the long press gesture.
Unrelated to your question, you should know that the line:
cell.tag = indexPath.row
should be:
cell.tag = indexPath.item
row
is used for UITableView
. item
is used for UICollectionView
.
But besides that, you really should avoid such code. If your collection view allows cells to be inserted, deleted, and/or reordered, then a cell's tag will no longer represent the item
you set.