decades
decades

Reputation: 827

Tap detection UIImageView within UIStackView within UIScrollView

I'm having a couple of UIImageViews in horizontal UIStackViews, wrapped in a vertical UIStackView, all together packed into a UIScrollView. All UIxx elements have "User Interaction enabled" checked. My UIViewController tries to catch the taps like so:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    if let touch = touches.first {

        if touch.view is UIImageView {
            print("Touch began in image view")
        }
    }
    super.touchesBegan(touches, with:event)
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    if let touch = touches.first{
        if touch.view is UIImageView {
            print("Touch ended in image view")
        }
    }
    super.touchesEnded(touches, with: event)
}

However, whatever I do I can't capture touches from within the UIImageViews contained in the stack view. Nothing happens then. The handlers are not invoked. There is another UIView on top of this, which reacts fine.

View-Layout in attached image

Any pointer welcome.

View Layout

Upvotes: 1

Views: 3154

Answers (1)

decades
decades

Reputation: 827

OK, here the answer.

1) Add a UITapGestureRecognizer to the UIScrollView in viewDidLoad

@IBOutlet weak var scrollView: UIScrollView!

...

let tapGesture = UITapGestureRecognizer(target: self, action: #selector(tapScrollView))
scrollView.addGestureRecognizer(tapGesture)

2) Give each UIImageView a unique tag

3) Find the tapped UIImageView

@objc func tapScrollView(sender: UITapGestureRecognizer) {
    for stackView in self.scrollView.subviews[0].subviews[0].subviews {
        for imageView in stackView.subviews {
            let location = sender.location(in: imageView)
            if let hitImageView = imageView.hitTest(location, with: nil) {
                print("Tapped", hitImageView.tag)
            }
        }
    }
}

Of course the identification of the proper container views depends on implementation, so in my case it was done by

self.scrollView.subviews[0].subviews[0].subviews

Upvotes: 1

Related Questions