Search code examples
iosuiscrollviewuiswipegesturerecognizer

Forward swipe gesture from UIView to UIScrollView


The main UIView in my app contains a single UIScrollView. I've added a UISwipeGestureRecognizer to the main view:

@IBOutlet weak internal var scrollView: UIScrollView!

override func viewDidLoad() {
    super.viewDidLoad()

    swipeRecognizer = UISwipeGestureRecognizer(target: self, action: #selector(handleSwipes(sender:)))
    view.addGestureRecognizer(swipeRecognizer)
  }

I've stubbed out the recognizer method like so... but I don't know how to pass the guesture on to the scrollview.

  func handleSwipes(sender: UISwipeGestureRecognizer) {
    if sender.direction == .left {
      // Send left swipe to the UIScrollView
    } else if (sender.direction == .right) {
      // Send right swipe to the UIScrollView
    }
  }

enter image description here


Solution

  • What you need is:

    1. a passthrough view that propagates touches through responder chain
    2. simulate swipe gestures on UIScrollView

    Passthrough view

    You can subclass your scrollView and override pointInside:event: method

    // you should convert this into Swift :(
    -(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
         for (UIView *view in self.subviews) {
             if (!view.hidden && view.userInteractionEnabled && 
                 [view pointInside:[self convertPoint:point toView:view] withEvent:event])
                 return YES;
        }
        return NO;
     }
    

    Then your custom scrollView will propagate the gestures on itself to other views below it and you can listen to swipe gestures in your mainView

    Simulating swipe gestures on UIScrollView

    You can do that by setContentOffset method of UIScrollView. That may feel buggy if you set content offset out of its bounds, be careful about that!

    However, IMHO, the best solution would be you changing your view hierarchy and listen to swipe gesture on a view at top of your scroll view.