UIPangestureRecognizer - 一个图像与另一个图像相交

Posted

技术标签:

【中文标题】UIPangestureRecognizer - 一个图像与另一个图像相交【英文标题】:UIPangestureRecognizer - One Image Interects with Another 【发布时间】:2020-02-07 18:08:43 【问题描述】:

我不知道如何从我的 UIPanGestureRecognizer 实验中获得某种行为。

当用户点击并按住一张图片,然后它与另一张图片相交时,就会触发一个行为。在这种情况下,行为是绿色或红色图像的不透明度变为 100%。

一旦用户继续在屏幕上拖动图像,并打破与绿色或红色图像的交叉点,我希望它的不透明度恢复到 50%。我的控制流越来越难看。我一直在调整它,但很难找到让我得到我想要的逻辑。

visual

 @objc func handlePan(sender: UIPanGestureRecognizer) 

    let imageOneView = sender.view!
    let translation = sender.translation(in: view)

    switch sender.state 

    case .began, .changed:
        imageOneView.center = CGPoint(x: imageOneView.center.x + translation.x, y: imageOne.center.y + translation.y)
        sender.setTranslation(CGPoint.zero, in: view)
        view.bringSubviewToFront(imageOne)
        if imageOne.frame.intersects(winImage.frame) 
            winImage.alpha = 1
         else 
            if imageOne.frame.intersects(loseImage.frame) 
                loseImage.alpha = 1
                winImage.alpha = 0.5

             else 
                return
            
        

    case .ended:
        if imageOne.frame.intersects(winImage.frame) 
            UIView.animate(withDuration: 0.3, animations: 
                self.imageOne.alpha = 0.0
            )
            performSegue(withIdentifier: "winnerDetailView", sender: self)
         else 
            if imageOne.frame.intersects(loseImage.frame) 
                UIView.animate(withDuration: 0.3, animations: 
                    self.imageOne.alpha = 0.0
                )
                navigationItem.rightBarButtonItem?.isEnabled = true
                loseImage.alpha = 0.5
             else 
                UIView.animate(withDuration: 0.3) 
                    self.imageOne.frame.origin = self.imageOneOrgin
                
            
        
    default:
        break
    

附加代码:https://github.com/ericmseitz/imageWar

谢谢。

【问题讨论】:

【参考方案1】:

几件事...

    控制流看起来不错。 要重置“赢”和“输”的 alpha,请在进入 handlePan() 时将它们都设置为 0.5。如果检测到相交,请将相应的设置为 1.0。在 UI 更新之前它不会更新,这不会在此函数内部发生。 如果您将可拖动视图嵌入到堆栈视图中(就像您在 GitHub 存储库中所做的那样),您将无法将它们放在彼此前面。 此外,如果您将可拖动视图嵌入到堆栈视图(或其他视图)中,请确保将框架转换为主视图的坐标空间。

这里是修改后的代码,基于您在问题中发布的内容和存储库中的布局(嵌入堆栈视图):

class ViewController: UIViewController 

    // IBOutlets

    @IBOutlet weak var winImage: UIImageView!
    @IBOutlet weak var loseImage: UIImageView!

    @IBOutlet weak var imageOne: UIImageView!
    @IBOutlet weak var imageTwo: UIImageView!
    @IBOutlet weak var imageThree: UIImageView!
    @IBOutlet weak var imageFour: UIImageView!

    // Constants and Variables

    var currentImageCenter = CGPoint.zero

    override func viewDidLoad() 
        super.viewDidLoad()

        [imageOne, imageTwo, imageThree, imageFour].forEach 
            let p = UIPanGestureRecognizer(target: self, action: #selector(handlePan(sender:)))
            $0?.addGestureRecognizer(p)
        

        winImage.alpha = 0.5
        loseImage.alpha = 0.5
    

    @objc func handlePan(sender: UIPanGestureRecognizer) 

        guard let imageOneView = sender.view else  return 

        let translation = sender.translation(in: view)

        // set alpha for both to 0.5
        // if either is intersected, it will be set to 1.0
        winImage.alpha = 0.5
        loseImage.alpha = 0.5

        switch sender.state 

        case .began:
            // track center of drag-view so we can return if needed
            currentImageCenter = imageOneView.center

        case .changed:
            imageOneView.center = CGPoint(x: imageOneView.center.x + translation.x, y: imageOneView.center.y + translation.y)
            sender.setTranslation(CGPoint.zero, in: view)

            // convert drag-view frame to view coordinate space
            guard let r = view.getConvertedFrame(fromSubview: imageOneView) else  return 

            view.bringSubviewToFront(imageOneView)
            if r.intersects(winImage.frame) 
                winImage.alpha = 1
             else 
                if r.intersects(loseImage.frame) 
                    loseImage.alpha = 1
                 else 
                    return
                
            

        case .ended:

            // convert drag-view frame to view coordinate space
            guard let r = view.getConvertedFrame(fromSubview: imageOneView) else  return 

            if r.intersects(winImage.frame) 
                UIView.animate(withDuration: 0.3, animations: 
                    imageOneView.alpha = 0.0
                )
                //performSegue(withIdentifier: "winnerDetailView", sender: self)
             else 
                if r.intersects(loseImage.frame) 
                    UIView.animate(withDuration: 0.3, animations: 
                        imageOneView.alpha = 0.0
                    )
                    navigationItem.rightBarButtonItem?.isEnabled = true
                 else 
                    UIView.animate(withDuration: 0.3) 
                        imageOneView.center = self.currentImageCenter
                    
                
            

        default:
            break
        
    

注意:以上需要这个UIView扩展来转换框架坐标:

// from Answer on ***: https://***.com/a/57261226/6257435
extension UIView 

    // there can be other views between `subview` and `self`
    func getConvertedFrame(fromSubview subview: UIView) -> CGRect? 

        // check if `subview` is a subview of self
        guard subview.isDescendant(of: self) else 
            return nil
        

        var frame = subview.frame
        if subview.superview == nil 
            return frame
        

        var superview = subview.superview
        while superview != self 
            frame = superview!.convert(frame, to: superview!.superview)
            if superview!.superview == nil 
                break
             else 
                superview = superview!.superview
            
        

        return superview!.convert(frame, to: self)
    


【讨论】:

DonMag - 这是一个很棒的帮助。我仍在努力理解这一切,但即使没有真正理解你的指导,我也成功地让它发挥了作用。说真的,你今天做出了很大的改变,我很感激你的时间和专业知识。

以上是关于UIPangestureRecognizer - 一个图像与另一个图像相交的主要内容,如果未能解决你的问题,请参考以下文章

如何在父视图中限制 UIPanGestureRecognizer

UIPanGestureRecognizer 干扰滚动

未调用 iOS 13 UIPanGestureRecognizer 选择器

Swift:获取 UIPanGestureRecognizer 的目标

当对象移动到某个帧时如何停止 UIPanGestureRecognizer

在父 UIView 中移动 UIView (UIPanGestureRecognizer)