Search code examples
swiftuiscrollviewuipangesturerecognizer

UIScrollView pan with 1 finger when zoomed in


I got a scrollView with some sub views added to it. Scrolling and zooming works fine.

What I would like to is when the scrollView is zoomed in, alter the behavior of the 1 finger touch to pan instead of scroll.

Right now if you are zoomed in and move around with 1 finger you can only scroll the zoomed in content. With two fingers you can pan around. This is the behaviour I would like to change.

I haven't found any solution to this issue and I don't really have any ideas except trying to alter the minimum and maximum touches required but it doesn't seem to work.

func scrollViewDidZoom(_ scrollView: UIScrollView) {
    scrollView.panGestureRecognizer.maximumNumberOfTouches = 1
}

func scrollViewDidEndZooming(_ scrollView: UIScrollView, with view: UIView?, atScale scale: CGFloat) {
    if scale == 1 {
        scrollView.panGestureRecognizer.maximumNumberOfTouches = 2
    }
}

Solution

  • I realized the issue I had was that each subview had their own scrollView (in my case my subviews wkWebViews). They were handling their own zoom even though I was trying to zoom from the UIScrollView.

    I took these steps to solve this issue.

    MyClass: UIViewController, UIScrollViewDelegate {
    
      // This view should handle the zooming 
      @IBOutlet var scrollView: UIScrollView!
    
      // .. and this view will contain all subviews to be zoomed
      @IBOutlet var wrapper: UIView!
    
      override func viewDidLoad() {
        super.viewDidLoad()
    
        self.scrollView.delegate = self
        self.addSViewsToScrollView()
      }
    
      func addViewsToScrollView () {
    
        // MARK: - Step 1 
        // .. set wkWebView scrollview maximum and minimum zoom scale to 1.
    
        let myArray: [WkWebView]? = [WkWebView(),WkWebView(),WkWebView()] 
    
        for view in myArray {
          wkWebView.scrollView.maximumZoomScale = 1
          wkWebView.scrollView.minimumZoomScale = 1
          wkWebView.isUserInteractionEnabled = false // This is key otherwise it wont work
          wkWebView.scrollView.isUserInteractionEnabled = false // .. this aswell
        }
    
        // MARK: - Step 2
        // .. add all views to a wrapper view
    
        for view in myArray {
          self.wrapperView.addSubview(view)
        }
    
      }
    
      func viewForZooming(in scrollView: UIScrollView) -> UIView? {
        return self.wrapper
      }
    }
    

    By returning a single view the panning in the zoomed in state works fine. Also the wkWebView scrollViews do not interfere with the zooming anymore.