【问题标题】:UIPangestureRecognizer - One Image Interects with AnotherUIPangestureRecognizer - 一个图像与另一个图像相交
【发布时间】: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

谢谢。

【问题讨论】:

    标签: ios swift xcode uipangesturerecognizer


    【解决方案1】:

    几件事...

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

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

    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 StackOverflow: https://stackoverflow.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 - 这是一个很棒的帮助。我仍在努力理解这一切,但即使没有真正理解你的指导,我也成功地让它发挥了作用。说真的,你今天做出了很大的改变,我很感激你的时间和专业知识。
    猜你喜欢
    • 1970-01-01
    • 2021-11-20
    • 2014-01-03
    • 2020-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-14
    • 1970-01-01
    相关资源
    最近更新 更多