Home > Software design >  Swift - UITapGestureRecognizer for parent view only
Swift - UITapGestureRecognizer for parent view only

Time:10-05

I have a UIViewController with a subview of a UIView. I add a UITapGestureRecognizer to the UIViewController to dismiss the view, but when I tap on the subview, the whole view still dismisses and I only want to dismiss when tapping the parent view.

var backgroundView = UIView()

override func viewDidLoad() {
    super.viewDidLoad()
    view.backgroundColor = .clear
    let tap = UITapGestureRecognizer(target: self, action: #selector(didTapOutsideBackgroundView))
    tap.numberOfTapsRequired = 1
    view.addGestureRecognizer(tap)
    setupUI()
}

func setupUI() {
    
    view.addSubview(backgroundView)
    backgroundView.translatesAutoresizingMaskIntoConstraints = false
    backgroundView.layer.cornerRadius = 8
    NSLayoutConstraint.activate([
        backgroundView.topAnchor.constraint(equalTo: view.topAnchor, constant: distanceFromTop ?? 0),
        backgroundView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
        backgroundView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
        backgroundView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
    ])
    backgroundView.backgroundColor = .systemBackground
    // add subviews to backgroundView
    backgroundView.addSubview(pageTitle)
    backgroundView.addSubview(closeButton)
    backgroundView.addSubview(itemLabel)
    backgroundView.addSubview(itemNameLabel)
    backgroundView.addSubview(priceLabel)
    backgroundView.addSubview(quantityLabel)
    backgroundView.addSubview(itemQuantityLabel)
    backgroundView.addSubview(itemOriginalPriceLabel)
}

@objc func didTapOutsideBackgroundView(sender: UITapGestureRecognizer) {
    print("called")
    dismiss(animated: true)
}

CodePudding user response:

You can find tapped view and ignore the tap if its a backgroundView with this in your didTapOutsideBackgroundView

@objc func didTapOutsideBackgroundView(sender: UITapGestureRecognizer) {

    let location = sender.location(in: self.view)
    if let view = self.view.hitTest(location, with: nil), let guester = view.gestureRecognizers {
        if guester.contains(sender) {
            print("Parent tapped")
            dismiss(animated: true)
        }
    } else {
        print("Ignore tap")
    }
}

CodePudding user response:

One solution can be check if it is subview or not & ignore based on that.

func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
    if touch.view.isDescendantOfView(yourSubView){ // this will check if this is subview of the main view or not..
        return false
    }
    return true
}
  • Related