Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UISwipeGestureRecognizer doesn't recognize swipe gesture initiated outside the view

func addSwipe() {
    self.isUserInteractionEnabled = true
    let directions: [UISwipeGestureRecognizerDirection] = [.right, .left]
    for direction in directions {
        let gesture = UISwipeGestureRecognizer(target: self, action: #selector(ViewCardContainer.handleSwipe(sender:)))
        gesture.direction = direction
        self.addGestureRecognizer(gesture)
    }
}

@objc func handleSwipe(sender: UISwipeGestureRecognizer) {
    print(sender.direction)
}

My UIViews:

+----------------+
|                |
|     +--------+ |
|  V1 |  V2    | |
+-----------------

I registered the UISwipeGestureRecognizer in V2 but if the swipe gesture is initiated from V1 going through V2, the swipe gesture won't be recognize in V2.

Is there anyway to make it work? Thanks in advance!

like image 485
zs2020 Avatar asked Mar 07 '23 19:03

zs2020


1 Answers

EDIT: I made a working sample project for you. You can swipe from the red square (v1) to the blue square (v2) and see in the log that a swipe is detected.

https://github.com/QuantumProductions/so_46781856

import UIKit

class ViewController: UIViewController {
    var view2: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()

        view.backgroundColor = UIColor.black

        let view1 = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
        view1.backgroundColor = UIColor.red
        view.addSubview(view1)

        view2 = UIView(frame: CGRect(x: 100, y: 0, width: 100, height: 100))
        view2.backgroundColor = UIColor.blue
        view.addSubview(view2)

        let swipeRecognizer = UISwipeGestureRecognizer(target: self, action: #selector(swipeDetected(_:)))
        swipeRecognizer.direction = .right
        view.addGestureRecognizer(swipeRecognizer)

    }

    func swipeDetected(_ sender: UIGestureRecognizer) {
        let location = sender.location(ofTouch: 0, in: view2)
        print("Location in view2")
        print(location)
        print("You swiped right")
    }
}

Original Answer:

This is intentional. The swipe detection is based view by view. Try out Apple apps like Contacts and you'll see that you can't press a button in the navigation bar after moving your finger up from the scrollview.

If you want your touch recognizer to be valid in V1 and V2:

  • Add the gesture recognizer in the parent view of both V1 & V2
  • Detect if the touch is within the rect of V2 (use touch.locationInView:V2)
  • If true, run your intended function

If this is a viewcontroller, you'll want to add the recognizer to self.view (It isn't clear from your example which view the recognizer is added to because there isn't context about what class your funcs are in)

You may need to disable user interaction on V1 and V2, if it's eating the touches and leave it ENABLED on the parent view.

like image 169
quantumpotato Avatar answered May 07 '23 22:05

quantumpotato