UIPangestureRecognizer - одно изображение взаимодействует с другим - PullRequest
1 голос
/ 07 февраля 2020

Я поставлен в тупик, как получить определенное поведение из моего эксперимента с UIPanGestureRecognizer.

Когда пользователь касается и удерживает изображение, а затем пересекается с другим изображением, возникает поведение. В этом случае поведение заключается в том, что непрозрачность зеленого или красного изображения достигает 100%.

Как только пользователь продолжит перетаскивать изображение по экрану и разрывает пересечение с зеленым или красным изображением, я бы хотел, чтобы его непрозрачность вернулась к 50%. Мой поток контроля становится ужасным. Я продолжаю дорабатывать его, но в тупик, чтобы найти логику c, которая дает мне то, что я хочу.

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 Ответ

0 голосов
/ 07 февраля 2020

Пара вещей ...

  1. Поток управления выглядит хорошо.
  2. Чтобы получить сброс «победа» и «проигрыш», установите их обоих на 0,5 при входе в handlePan(). Если обнаружено пересечение, установите соответствующее значение 1,0. Он не будет обновляться до обновления пользовательского интерфейса, что не произойдет внутри этой функции.
  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)
    }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...