Search code examples
swiftuibuttonuikituigesturerecognizer

How would I make a UiPanGestureRecognizer check if the finger is in the buttons frame?


I am trying to make an app where the user could drag a finger on top of multiple buttons and get some actions for each button.

There was a similar question from a while back but when I tried to use CGRectContainsPoint(button.frame, point) it said it was replaced with button.frame.contains(point) but this didn’t seem to work for me. Here is a link to the Photo

What I have done so far:

var buttonArray:NSMutableArray!

override func viewDidLoad()
{
    super.viewDidLoad()
    let panGesture = UIPanGestureRecognizer(target: self, action: #selector(panGestureMethod(_:)))
    a1.addGestureRecognizer(panGesture)
    a2.addGestureRecognizer(panGesture)
}
@objc func panGestureMethod(_ gesture: UIPanGestureRecognizer) {
    
    
    if gesture.state == UIGestureRecognizer.State.began {
        buttonArray = NSMutableArray()
    }
    
    let pointInView = gesture.location(in: gesture.view)
    
    if !buttonArray.contains(a1!) && a1.frame.contains(pointInView) {
        buttonArray.add(a1!)
        a1Tapped(a1)
    }
    else if !buttonArray.contains(a2!) && a2.frame.contains(pointInView) {
        buttonArray.add(a2!)
        a2Tapped(a2)
    }

The code did run fine but when I tried to activate the drag nothing happened. Any tips?


Solution

  • You want behavior similar to the system keyboard I assume? CGRectContainsPoint is not deprecated: See the docs. In Swift it's written like frame.contains().

    When dealing with rects and points you have to make sure both are translated to the same coordinate system first. To do so you can use the convert to/from methods on UIView: See (the docs).

    In your case smth. like the following should work (first translate button frames, then check if the point is inside):

    func touchedButtonForGestureRecognizer(_ gesture: UIPanGestureRecognizer) -> UIView? {
        let pointInView = gesture.location(in: gesture.view)
        for (button in buttonArray) {
            let rect = gesture.view.convert(button.frame from:button.superview)
            if (rect.contains(pointInView)) {
              return button
            }
        }
        return nil
    }