如何将 UITapGestureRecognizer 添加到 UICollectionViewCell 中的图像

Posted

技术标签:

【中文标题】如何将 UITapGestureRecognizer 添加到 UICollectionViewCell 中的图像【英文标题】:How to add UITapGestureRecognizer to an image within UICollectionViewCell 【发布时间】:2021-02-12 05:36:40 【问题描述】:

我的每个单元格都包含一个 imageView。目标是拥有它,以便在任何时候点击或滑动单元格(或 imageView)时,图像都会随着相应的点击或滑动动画而变化。 (点击动画缩小后扩大,而滑动动画将imageView旋转180度)

起初我在我的收藏视图的didSelectItemAt 方法中设置了我的点击功能,并且效果很好。但是,当我尝试添加滑动功能时,我发现任何用户与单元格的交互都会触发相同的点击动画。

所以,现在我正在尝试在cellForItemAt 中设置点击功能。但是,由于某种原因没有调用分接选择器。任何想法为什么?

我正在使用 UICollectionViewController。 Xcode 12,快速 5。

编辑

按照@Sandeep Bhandari 的建议,我现在正在实现一个协议,以在单元格(对点击手势具有强引用)和 UICollectionViewController 之间进行通信。但是,仍然没有调用选择器。

GameTileCell

@objc protocol GameTileCellProtocol 
     func didTapImageView(for cell: GameTileCell)


class GameTileCell: UICollectionViewCell 

     // other properties
     var gesture: UITapGestureRecognizer?
     weak var delegate: GameTileCellProtocol?

    override init(frame: CGRect) 
        super.init(frame: frame)
        // call configure cell method
        
        gesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))
        gameTileImageView.isUserInteractionEnabled = true
        gameTileImageView.addGestureRecognizer(gesture!)
        
    
    
    // storyboard init
    // configure cell method defined
    
    @objc func handleTap(_ sender: UITapGestureRecognizer) 
        self.delegate?.didTapImageView(for: self)
        print("handleTap")
    

UICollectionViewController

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: GameTileCell.reuseID, for: indexPath) as! GameTileCell
        setImageAndColor(for: cell)
        cell.delegate = self
        return cell
    
// other methods

extension GameTileCVC: GameTileCellProtocol 
func didTapImageView(for cell: GameTileCell) 
    UIView.animate(withDuration: 0.4) 
        cell.gameTileImageView.transform = CGAffineTransform(scaleX: 0.01, y: 0.01)
     completion:  (_ finished: Bool) in
        UIView.animate(withDuration: 0.4) 
            self.setImageAndColor(for: cell)
            cell.gameTileImageView.transform = CGAffineTransform.identity
        
    
    print(#function)

【问题讨论】:

添加了新答案请检查 【参考方案1】:

您正在cellForItemAt indexPath: IndexPath) 方法内创建一个轻击手势识别器,这意味着它是该方法内的一个局部变量。此手势识别器的范围仅在此函数cellForItemAt indexPath: IndexPath) 内,一旦控制离开函数的范围手势识别器将被释放,因此触摸将不起作用。

您需要保持对点击手势识别器的强引用,因此我建议将此点击手势识别器从您的 ViewController 移动到 GameTileCell

因此,将您的 GameTiteCell 实现更改为类似

class GameTileCell: UICollectionViewCell 
    let gesture: UITapGestureRecognizer
    weak var delegate: GameTitleCellProtocol?
    //other declarations of yours

    override init(frame: CGRect) 
        super.init(frame: frame)
        gameTileImageView.isUserInteractionEnabled = true
        gesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))
        self.gameTileImageView.addGestureRecognizer(gesture)
    

    @objc func handleTap(_ sender: UITapGestureRecognizer) 
        self.delegate?.didTapImageView(for: self)
    

声明一个协议以在您的单元格和您的 ViewController 之间进行通信。让我们称之为

@objc protocol GameTitleCellProtocol 
    func didTapImageView(for cell: GameTileCell)

最后,让您的 ViewController 成为您的 GameTileCellcellForRowAtIndexPath 中的代表

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: GameTileCell.reuseID, for: indexPath) as! GameTileCell
    setImageAndBgColor(for: cell)
    cell.delegate = self    
    return cell

最后让你的 ViewController 确认GameTitleCellProtocol 协议

extension YourViewController: GameTitleCellProtocol 
    func didTapImageView(for cell: GameTileCell) 
        UIView.animate(withDuration: 0.4) 
            cell.gameTileImageView.transform = CGAffineTransform(scaleX: 0.01, y: 0.01)
         completion:  (_ finished: Bool) in
            UIView.animate(withDuration: 0.4) 
                self.setImageAndBgColor(for: cell)
                cell.gameTileImageView.transform = CGAffineTransform.identity
            
        
    

【讨论】:

感谢您再次查看!我确实实施了您的建议,但仍然没有看到任何变化。我在didTapImageViewhandleTap 选择器中放置了打印语句,但都没有打印。应用不会崩溃,但点击单元格时不会发生任何事情。 @melh0n: 一个一个调试 1. 你在imageView上启用用户交互了吗?我已将其设置在 init 请检查是否触发了 init,是否执行了其中的语句 2.您的分接选择器是否被触发?在didTapImageView 中设置一个断点并检查控制是否到达那里? 3. 您是否将视图控制器设置为 cellForRowAtIndexPath 中的单元格委托。最后,当您说“点击单元格时没有任何反应”时,在 imageView 上添加了点击手势,我们仅调试 imageView 点击而不是单元格点击,如果单元格点击不工作,因为allowsSelection 存在 设置为 false 我在之前的回答中错误地提到了 我已经编辑了 OP 以包含您的建议作为实施。 1. 正在触发初始化并启用用户交互。 2.点击选择器没有被触发!控制未达到didTapImageView 3. VC 在cellForItemAt indexPath 中设置为单元格的代表,我想这就是您要说的(不是行)。 正确,点击手势已添加到 imageView。我的 imageView 固定在其单元格的边缘,因此当用户点击 imageView 时,他们实际上也在点击单元格......哦,allowsSelection 目前没有设置任何内容。【参考方案2】:

如果您想为您的单元格添加点击和滑动功能,您需要为每个单元格定义一个单独的手势识别器:

let tap = UITapGestureRecognizer(target: self, action:#selector(tapAction(_:)))
let swipe = UISwipeGestureRecognizer(target: self, action:#selector(swipeAction(_:)))
view.addGestureRecognizer(tap)
view.addGestureRecognizer(swipe)

为什么你的选择器动作没有被调用:你有没有在这一行设置断点?

if let indexPath = self.collectionView?.indexPathForItem(at: sender.location(in: self.collectionView)) 

我认为 if 可能不会变成积极的,因此你的行动什么也不做。

【讨论】:

抱歉延迟回复!控件甚至没有到达if let indexPath 处设置的断点。我想这再次证实了我没有调用处理程序的假设:\

以上是关于如何将 UITapGestureRecognizer 添加到 UICollectionViewCell 中的图像的主要内容,如果未能解决你的问题,请参考以下文章

如何将thinkcmf导入eclipse

如何将CString转换成wstring

如何将Ios文件上传到

Qt如何将文字变成图片?

如何将Bitmap保存为本地图片文件?

在MATLAB中如何将图导出