How do you determine the drag and drop location in Swift 5?

Viewed 486

I have mocked up a simple example of what I am trying to accomplish:

enter image description here

A ViewController contains 4 "drop zone" UIImageViews (e.g. dropZone1). A 5th UIImageView (playerCard) can be dragged and dropped onto any of the drop zones, but nowhere else.

I cannot figure out the way to determine which of the 4 drop zones is where the user has dragged and dropped the playerCard.

My thought was to set some sort of variable in dropInteraction canHandle and then use that in dropInteraction performDrop to take the appropriate action. But I can't figure out how to do it.

1 Answers
class ViewController: UIViewController {

let bounds = UIScreen.main.bounds
let imageViewWidth: CGFloat = 100
let imageViewHeight: CGFloat = 200
let inset: CGFloat = 40

var arrayDropZones = [DropZoneCard]()

var initialFrame: CGRect {
    get {
        return CGRect(x: bounds.width - imageViewWidth,
                           y: bounds.height - imageViewHeight,
                           width: imageViewWidth,
                           height: imageViewHeight
        )
    }

}

override func viewDidLoad() {
    super.viewDidLoad()

    addDropZones()
    addNewCard()
}
}

extension ViewController {
func addDropZones() {
    let dropZone1 = getDropZoneCard()
    dropZone1.frame = CGRect(x: inset, y: inset, width: imageViewWidth, height: imageViewHeight)

    let dropZone2 = getDropZoneCard()
    let x = bounds.width - imageViewWidth - inset
    dropZone2.frame = CGRect(x: x, y: inset, width: imageViewWidth, height: imageViewHeight)

    let dropZone3 = getDropZoneCard()
    let y = inset + imageViewHeight + inset
    dropZone3.frame = CGRect(x: inset, y: y, width: imageViewWidth, height: imageViewHeight)

    let dropZone4 = getDropZoneCard()
    dropZone4.frame = CGRect(x: x, y: y, width: imageViewWidth, height: imageViewHeight)


    [dropZone1, dropZone2, dropZone3, dropZone4].forEach {
        view.addSubview($0)
        self.arrayDropZones.append($0)
    }
}

func getNewCard() -> UIImageView {
    let imageView = UIImageView()
    imageView.isUserInteractionEnabled = true
    imageView.backgroundColor = .green

    imageView.frame = initialFrame

    let panGesture = UIPanGestureRecognizer(target: self, action:(#selector(handleGesture(_:))))
    imageView.addGestureRecognizer(panGesture)

    return imageView
}

func getDropZoneCard() -> DropZoneCard {
    let dropZone = DropZoneCard()
    dropZone.isUserInteractionEnabled = true
    dropZone.backgroundColor = .yellow
    return dropZone
}

func addNewCard() {
    let imageView = getNewCard()
    view.addSubview(imageView)
}

@objc func handleGesture(_ recognizer: UIPanGestureRecognizer) {

    let translation = recognizer.translation(in: self.view)
    if let view = recognizer.view {

        view.center = CGPoint(x:view.center.x + translation.x,
                              y:view.center.y + translation.y)

        if recognizer.state == .ended {
            let point = view.center
            for dropZone in arrayDropZones {
                if dropZone.frame.contains(point) {
                    dropZone.append(card: view)
                    addNewCard()
                    return
                }
            }

            view.frame = initialFrame
        }
    }

    recognizer.setTranslation(.zero, in: view)
}
}

class DropZoneCard: UIImageView {
private(set) var arrayCards = [UIView]()

func append(card: UIView) {
    arrayCards.append(card)
    card.isUserInteractionEnabled = false
    card.frame = frame
}
}
Related