为什么UITapGestureRecognizer在Swift集合视图中不能正确地处理单元格图像?

huangapple go评论62阅读模式
英文:

Why does UITapGestureRecognizer not work properly for cell images in Swift collection view?

问题

我已为集合视图单元格图像添加了UITapGestureRecognizer,如下所示:

代码:使用此代码,如果我点击两个单元格图像,则两者都会显示。在这里,如果我点击第二个单元格图像,如何将第一个图像从前景中移除?

在这里,当我在newImageView之外(但在集合视图上)点击时,touchesBegan不会被调用。是否有解决方法?

代码的输出屏幕

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: FriendCollectionViewCell.cellId, for: indexPath) as! FriendCollectionViewCell

    let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(cellTappedMethod(_:)))
    cell.profileImageView?.gestureRecognizers?.removeAll()
    cell.profileImageView.isUserInteractionEnabled = true
    cell.profileImageView.tag = indexPath.row
    cell.profileImageView.addGestureRecognizer(tapGestureRecognizer)

    return cell
}

@objc func cellTappedMethod(_ sender: UITapGestureRecognizer) {
    let imageView = sender.view as! UIImageView
    let newImageView = UIImageView(image: imageView.image)
    newImageView.frame = CGRect(x: 0, y: 0, width: self.view.frame.width * 0.7, height: 300.0)
    UIView.animate(withDuration: 0.2) { [self] in
        newImageView.center = CGPoint(x: UIScreen.main.bounds.center.x - 15, y: UIScreen.main.bounds.center.y - 200)
        newImageView.backgroundColor = UIColor.clear
        newImageView.contentMode = .scaleAspectFit
        newImageView.isUserInteractionEnabled = true
        let tap = UITapGestureRecognizer(target: self, action: #selector(dismissFullscreenImage))
        newImageView.addGestureRecognizer(tap)
        self.view.addSubview(newImageView)
    }
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    let touch = touches.first
    print("touch..outside")
    
    if let sender = touch?.view?.gestureRecognizers?.first {
        print(sender.view?.tag)
        sender.view?.removeFromSuperview()
    }
}

@objc func dismissFullscreenImage(sender: UITapGestureRecognizer) {
    UIView.animate(withDuration: 0.2) { [self] in
        sender.view?.removeFromSuperview()
    }
}

如果我点击单元格图像,如何移除所有位于前景中的图像,请指导我。

英文:

I have added UITapGestureRecognizer for collectionview cell image like

code: with this code if i tap on two cell images then both are showing. Here if i tap on second cell image then how to remove first image from foreground

here touchesBegan not calling when i tap on outside of the newImageView(but on collectionview) why? is there any solution for this

o/p screen of the code

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -&gt; UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: FriendCollectionViewCell.cellId, for: indexPath) as! FriendCollectionViewCell

let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(cellTappedMethod(_:)))
cell.profileImageView?.gestureRecognizers?.removeAll()
cell.profileImageView.isUserInteractionEnabled = true
cell.profileImageView.tag = indexPath.row
cell.profileImageView.addGestureRecognizer(tapGestureRecognizer)


return cell

}

@objc func cellTappedMethod(_ sender: UITapGestureRecognizer){

let imageView = sender.view as! UIImageView
let newImageView = UIImageView(image: imageView.image)
newImageView.frame = CGRect(x: 0, y: 0, width: self.view.frame.width * 0.7, height: 300.0)//UIScreen.main.bounds
UIView.animate(withDuration: 0.2) { [self] in
    
    newImageView.center = CGPoint(x: UIScreen.main.bounds.center.x - 15, y: UIScreen.main.bounds.center.y - 200)
    
    newImageView.backgroundColor = UIColor.clear
    newImageView.contentMode = .scaleAspectFit
    newImageView.isUserInteractionEnabled = true
    let tap = UITapGestureRecognizer(target: self, action: #selector(dismissFullscreenImage))
    newImageView.addGestureRecognizer(tap)
    
    self.view.addSubview(newImageView)
}
}

override func touchesBegan(_ touches: Set&lt;UITouch&gt;, with event: UIEvent?)
{

let touch = touches.first
print(&quot;touch..outside&quot;)

var sender = UITapGestureRecognizer()
print(sender.view?.tag)

if ((touch?.view) != nil){
    print(&quot;touch..&quot;)
    sender.view?.removeFromSuperview()
}
}



@objc func dismissFullscreenImage(sender: UITapGestureRecognizer) {
UIView.animate(withDuration: 0.2) { [self] in
    sender.view?.removeFromSuperview()
}
}

if i tap on cell image then how to remove all image which are in foreground. please guide me

答案1

得分: 1

为了实现在点击新单元格图像时从前景中删除先前的图像的所需行为,您可以跟踪当前显示的图像视图,并在添加新图像之前将其删除。

var currentImageView: UIImageView?

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: FriendCollectionViewCell.cellId, for: indexPath) as! FriendCollectionViewCell

    let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(cellTappedMethod(_:)))
    cell.profileImageView?.gestureRecognizers?.removeAll()
    cell.profileImageView.isUserInteractionEnabled = true
    cell.profileImageView.tag = indexPath.row
    cell.profileImageView.addGestureRecognizer(tapGestureRecognizer)

    return cell
}

@objc func cellTappedMethod(_ sender: UITapGestureRecognizer) {
    let imageView = sender.view as! UIImageView

    currentImageView?.removeFromSuperview()

    let newImageView = UIImageView(image: imageView.image)
    newImageView.frame = CGRect(x: 0, y: 0, width: self.view.frame.width * 0.7, height: 300.0)
    newImageView.center = CGPoint(x: UIScreen.main.bounds.center.x - 15, y: UIScreen.main.bounds.center.y - 200)
    newImageView.backgroundColor = UIColor.clear
    newImageView.contentMode = .scaleAspectFit
    newImageView.isUserInteractionEnabled = true

    let tap = UITapGestureRecognizer(target: self, action: #selector(dismissFullscreenImage))
    newImageView.addGestureRecognizer(tap)
    self.view.addSubview(newImageView)
    currentImageView = newImageView
}

@objc func dismissFullscreenImage(sender: UITapGestureRecognizer) {
    sender.view?.removeFromSuperview()
    currentImageView = nil
}

在这段代码中,currentImageView 变量在类级别声明,以跟踪当前显示在屏幕上的图像视图。当单元格图像被点击时,先前的图像视图(如果有的话)会从父视图中删除,然后添加新的图像视图。currentImageView 变量会被更新为新的图像视图,当关闭全屏图像时,会清除引用以表示当前没有显示图像视图。

至于在点击 newImageView 外部时 touchesBegan 未被调用的问题,这是因为 newImageView 位于集合视图的上方并拦截了触摸事件。一种解决方法是子类化 UICollectionView 并在子类中覆盖 touchesBegan 方法。

class MyCollectionView: UICollectionView {
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesBegan(touches, with: event)
    }
}

以上是您要求的代码部分的翻译。

英文:

To achieve the desired behavior of removing the previous image from the foreground when tapping on a new cell image, you can keep track of the currently displayed image view and remove it before adding a new one.

var currentImageView: UIImageView?

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -&gt; UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: FriendCollectionViewCell.cellId, for: indexPath) as! FriendCollectionViewCell
    
    let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(cellTappedMethod(_:)))
    cell.profileImageView?.gestureRecognizers?.removeAll()
    cell.profileImageView.isUserInteractionEnabled = true
    cell.profileImageView.tag = indexPath.row
    cell.profileImageView.addGestureRecognizer(tapGestureRecognizer)
    
    return cell
}

@objc func cellTappedMethod(_ sender: UITapGestureRecognizer) {
    let imageView = sender.view as! UIImageView
    
    currentImageView?.removeFromSuperview()
    
    let newImageView = UIImageView(image: imageView.image)
    newImageView.frame = CGRect(x: 0, y: 0, width: self.view.frame.width * 0.7, height: 300.0)
    newImageView.center = CGPoint(x: UIScreen.main.bounds.center.x - 15, y: UIScreen.main.bounds.center.y - 200)
    newImageView.backgroundColor = UIColor.clear
    newImageView.contentMode = .scaleAspectFit
    newImageView.isUserInteractionEnabled = true
    
    let tap = UITapGestureRecognizer(target: self, action: #selector(dismissFullscreenImage))
    newImageView.addGestureRecognizer(tap)
    self.view.addSubview(newImageView)
    currentImageView = newImageView
}

@objc func dismissFullscreenImage(sender: UITapGestureRecognizer) {
    sender.view?.removeFromSuperview()
    currentImageView = nil
}

In this code the currentImageView variable is declared at the class level to keep track of the image view currently displayed on the screen. When a cell image is tapped, the previous image view (if any) is removed from the superview before adding a new one. The currentImageView variable is updated with the new image view, and when dismissing the full-screen image, the reference is cleared to indicate that no image view is currently displayed.

As for the issue with touchesBegan not being called when tapping outside the newImageView, it's because the newImageView is on top of the collection view and intercepts the touch events. One solution is to subclass UICollectionView and override the touchesBegan method in the subclass.

class MyCollectionView: UICollectionView {
    override func touchesBegan(_ touches: Set&lt;UITouch&gt;, with event: UIEvent?) {
        super.touchesBegan(touches, with: event)
    }
}

huangapple
  • 本文由 发表于 2023年6月4日 23:35:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/76401162.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定