32

Does anyone know a way to temporarily turn off zooming when using a UIScrollView?

I see that you can disable scrolling using the following:

self.scrollView.scrollEnabled = false;

but I'm not seeing a similar command for zooming. Any thoughts?

Ahmad F
  • 30,560
  • 17
  • 97
  • 143
CodingWithoutComments
  • 35,598
  • 21
  • 73
  • 86

10 Answers10

50

If you want to disable the user's ability to zoom through gestures then in iOS 5 and above you can disable the pinch gesture. This still allows you to control the scroll view from code...

scrollView.pinchGestureRecognizer.enabled = NO;

similarly for pan...

scrollView.panGestureRecognizer.enabled = NO;

This must be called in - (void)viewDidAppear:(BOOL)animated or later as otherwise the system resets it to enabled.

Swift 4.x and above:

imageZoomView.pinchGestureRecognizer?.isEnabled = false / true

Hadži Lazar Pešić
  • 1,031
  • 1
  • 13
  • 20
combinatorial
  • 9,132
  • 4
  • 40
  • 58
  • 1
    this is the best answer and should totes be the accepted one! this doesn't seem to affect any of the zoom delegates or muck with any of your current min/max zoomScale settings, which as someone pointed out, may not necessarily reflect if the user zoomed it or not. – taber Mar 28 '15 at 20:15
  • 1
    In addition to being the cleanest alternative, it is also the most simple! Given that people are still learning from it almost six years later (and it works fine in iOS 8), I agree that it should get the green check mark. – Tony Adams May 13 '15 at 17:06
  • @oarfish what part of it doesn't work? zooming still works after you have called `scrollView.pinchGestureRecognizer.enabled = NO;` ? – combinatorial May 14 '15 at 15:43
  • @combinatorial Yes, exactly. – oarfish May 14 '15 at 21:44
  • have you checked at the point you are calling it that scrollview is not nil? – combinatorial May 14 '15 at 22:01
  • Won't work for me either (iOS 9 beta). Documentation also says that this is [read-only](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIScrollView_Class/#//apple_ref/occ/instp/UIScrollView/pinchGestureRecognizer) – heikomania Jul 05 '15 at 19:04
  • Updated answer.... also the recognizer is readonly, which means you can't replace it with another recognizer. The enabled property on the recognizer is not readonly. – combinatorial Jul 05 '15 at 20:00
  • Had the same problem under iOS 9 Beta 5. Calling it somewhere after `viewDidAppear` fixed it for me. – mangerlahn Aug 18 '15 at 23:27
  • 1
    If you set zoomScale, better set gesture enabled again. – NSDeveloper Jan 18 '17 at 09:02
  • 1
    In case you are subclassing the UIScrollView, `self.pinchGestureRecognizer.enabled = false` (and the other one), can be called in `-(void)didMoveToWindow`. – Mr. Goldberg May 01 '20 at 16:12
30

Following fbrereto's advice above, I created two functions lockZoom and unlockZoom. When locking Zoom i copied my max and min zoom scales to variables then set the max and min zoom scale to 1.0. Unlocking zoom just reverses the process.

-(void)lockZoom
{
    maximumZoomScale = self.scrollView.maximumZoomScale;
    minimumZoomScale = self.scrollView.minimumZoomScale;

    self.scrollView.maximumZoomScale = 1.0;
    self.scrollView.minimumZoomScale = 1.0;
}

-(void)unlockZoom
{

    self.scrollView.maximumZoomScale = maximumZoomScale;
    self.scrollView.minimumZoomScale = minimumZoomScale;

}
CodingWithoutComments
  • 35,598
  • 21
  • 73
  • 86
17

Also you can return "nil" as zooming view in UIScrollViewDelegate:

- (UIView *) viewForZoomingInScrollView:(UIScrollView *) scrollView
{
    return canZoom?view:nil;
}
derand
  • 171
  • 2
  • 3
  • 1
    I really like this approach, but be careful. Delegate methods like "scrollViewDidEndZooming" will still be called annoyingly. – Ralphleon Apr 19 '12 at 01:19
  • I have seen this as well. UIKit is automatically zooming my scroll view out to `zoomScale` 1.0 after I set `scrollEnabled` to `NO` – Kyle Redfearn Jan 24 '17 at 22:35
  • The problem with this solution is whenever you access `scrollView.zoomScale`, this method gets called, which returns nil and as a consequence returns 1.0 as the `zoomScale` of your scroll view – Kyle Redfearn Jan 24 '17 at 23:32
  • I observe one issue with this problem. When keyboard comes up for text field it doesn't scroll the screen. (Text field is inside a web view which loads my page on server) – Yugandhar Pathi Aug 15 '17 at 21:33
11

Check setting minimumZoomScale and maximumZoomScale; According to the docs:

maximumZoomScale must be greater than minimumZoomScale for zooming to be enabled.

So, setting the values to be the same should disable zooming.

fbrereto
  • 35,429
  • 19
  • 126
  • 178
5

I have tried setting minimumZoomScale and maximumZoomScale properties of UIScrollView to 1 or isMultipleTouchEnabled property of UIView to false or return nil from viewForZooming(in:) of UIScrollViewDelegate but none worked. In my case, after several trial and error, the following works in my case [Tested on iOS 10.3]:

class MyViewController: UIViewController {
   var webView: WKWebView?

   override viewDidLoad() {
      super.viewDidLoad()

      //...
      self.webView.scrollView.delegate = self
      //...
   }
}

extension MyViewController: UIScrollViewDelegate { 
   func scrollViewWillBeginZooming(_ scrollView: UIScrollView, with view: UIView?) {
      scrollView.pinchGestureRecognizer?.isEnabled = false
   }
}
yohannes
  • 1,022
  • 11
  • 13
  • I think this is specific to the WKWebView's scrollview. I have been messing with this for days. The only downside to your solution I have found is that sometimes the webpage does not scale properly on rotation. This happens with or without your solution, but since the user can't zoom out to fix the scale, we have to scroll horizontally. Good find with this!! – hidden-username Apr 05 '18 at 23:32
  • Disable magnification gesture in WKWebView: https://stackoverflow.com/questions/25553711/disable-magnification-gesture-in-wkwebview – black_pearl Jun 30 '20 at 09:16
2

here, my solution for stop zooming on scrollview.

self.scrollView.minimumZoomScale=self.scrollView.maximumZoomScale;
Chirag Lukhi
  • 1,528
  • 17
  • 41
  • For me, the nice thing about this solution to eliminating the zoom is that I am still able to use the pinchGestureRecognizer. – Jerry Frost Oct 07 '15 at 08:04
2

I know this is a really old question but I made a slight variation for my purposes.

I wanted to be able to easily tell if the zooming was in fact enabled/disabled without relying on a comparison between scrollView.minimumZoomScale == scrollView.maximumZoomScale, which could possibly not reflect whether zooming was actually enabled/disabled.

So I did this

// .h
@property (assign, nonatomic, getter=isZoomEnabled) BOOL zoomEnabled;

// .m
@synthesize zoomEnabled = _zoomEnabled;

- (void)setZoomEnabled:(BOOL)zoomEnabled;
{
  _zoomEnabled = zoomEnabled;

  UIScrollView *scrollView = self.scrollView;

  if (zoomEnabled) {
    scrollView.minimumZoomScale = self.minimumZoomScale;
    scrollView.maximumZoomScale = self.maximumZoomScale;
  } else {
    scrollView.minimumZoomScale = 0.0f;
    scrollView.maximumZoomScale = 0.0f;
  }
}

The values for self.minimumZoomScale and self.maximumZoomScale are set at the time the UIScrollView is configured.

This gives me the ability to set/ask if zooming is enabled.

myViewController.zoomEnabled = YES;
myViewController.isZoomEnabled;
Paul.s
  • 38,494
  • 5
  • 70
  • 88
1

Swift 3 Version:

func lockScrollViewZooming() {
    scrollView.minimumZoomScale = 1.0
    scrollView.maximumZoomScale = 1.0
    scrollView.bounces = false
    scrollView.bouncesZoom = false

    // Also, if you have double tap recognizer,
    // remember to remove it
    scrollView.removeGestureRecognizer(doubleTapGestureRecognizer)
}

func unlockScrollViewZooming() {
    scrollView.minimumZoomScale = 1.0
    scrollView.maximumZoomScale = 4.0
    scrollView.bounces = true
    scrollView.bouncesZoom = true

    // Also, if you have double tap recognizer,
    // remember to add it
    scrollView.removeGestureRecognizer(doubleTapGestureRecognizer)
}

Note that doubleTapGestureRecognizer should be an instance variable. It should be similar to:

private lazy var doubleTapGestureRecognizer: UITapGestureRecognizer = {
    let doubleTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleDoubleTap(_:)))
    doubleTapGestureRecognizer.numberOfTapsRequired = 2
    doubleTapGestureRecognizer.delegate = self

    return doubleTapGestureRecognizer
}()

@objc private func handleDoubleTap(_ recognizer: UITapGestureRecognizer) {
    //scrollView.setZoomScale((scrollView.zoomScale > scrollView.minimumZoomScale) ? scrollView.minimumZoomScale : scrollView.maximumZoomScale, animated: true)

    if scrollView.zoomScale > scrollView.minimumZoomScale {
        scrollView.setZoomScale(scrollView.minimumZoomScale, animated: true)
    } else {
        let touchLocation = recognizer.location(in: recognizer.view)
        scrollView.zoom(to: CGRect(origin: touchLocation, size: CGSize(width: 22.0, height: 20.0)), animated: true)
    }
}
Ashok
  • 5,585
  • 5
  • 52
  • 80
Ahmad F
  • 30,560
  • 17
  • 97
  • 143
1

You need to turn off Two Fingers and Double Tap of scroll view

self.scrollView.delegate = self

And

extension YourViewController: UIScrollViewDelegate {
   func scrollViewWillBeginZooming(_ scrollView: UIScrollView, with view: UIView?) {
       scrollView.pinchGestureRecognizer?.isEnabled = false
   }

   func viewForZooming(in scrollView: UIScrollView) -> UIView? {
       return nil
   }
}
Ten
  • 1,426
  • 1
  • 14
  • 18
0

If you want to disable only zooming with pinch gesture, below code does the trick.

scrollView.pinchGestureRecognizer?.requireGestureRecognizerToFail(scrollView.panGestureRecognizer)
mmtootmm
  • 800
  • 6
  • 17