Search code examples
iosswiftuigesturerecognizeruipangesturerecognizer

How to set up gesture recognizers for an unknown number of subviews


I have a main view called mainCanvasView, where I conform to UIGestureRecognizerDelegate and have set up the pan gesture as follows:

    let panGesture = UIPanGestureRecognizer(target: self, action:#selector(self.handlePanGesture(gesture:)))
    self.mainCanvasView.addGestureRecognizer(panGesture)  


    func handlePanGesture(gesture: UIPanGestureRecognizer) {
        if gesture.state == UIGestureRecognizerState.began || gesture.state == UIGestureRecognizerState.changed{
            let translation = gesture.translation(in: view)
            gesture.view?.transform = (gesture.view?.transform)!.translatedBy(x: translation.x, y: translation.y)
            gesture.setTranslation(CGPoint(x: 0, y: 0), in: view)
        }
    }

At the moment, the outcome looks like this:

My goal is not to pan the mainCanvasView, but subsequent subviews that the users may add to the mainCanvasView. I know that I shouldn't be adding a pan gesture to every new subview that gets added to mainCanvasView. How would I be able to detect the top subview that the gesture has panned on in my mainCanvasView?

Illustrated example of what's currently not working:

enter image description here


Solution

  • You should gesture in all subview because if subview moved out of the bounds of the main container view no gesture will be work on it. either you create your main view full height and in front or add gesture to each and every subview of it when you are adding as subview.

    Still I am posting code where I have created Grey colour main view and white view are subview of it

    Here is my solution

    What you need is to find subview which has been touched during the pan gesture

    I have created DEMO where I have created One Main View which contains 3 subviews (If you have image make sure you enable user interaction)

    func handlePanGesture(gesture: UIPanGestureRecognizer) {
    
        if gesture.state == UIGestureRecognizerState.began || gesture.state == UIGestureRecognizerState.changed {
    
            var viewNew = UIView(frame: view.frame)
    
            for view in self.viewMain.subviews {
                let point = gesture.location(in: view)
                if (view.hitTest(point, with: nil) != nil) {
                    viewNew = view
                    break
    
                } else {
                    print("Not Tapped")
                }
            }
    
            print("View Tapped")
    
    
            let translation = gesture.translation(in: view)
            viewNew.transform = (viewNew.transform).translatedBy(x: translation.x, y: translation.y)
            gesture.setTranslation(CGPoint(x: 0, y: 0), in: viewNew)
    
    
    
    
        }
    }
    

    enter image description here