iOS: Can I override pinch in/out behavior of UIScr

2020-02-12 07:37发布

问题:

I'm drawing a graph on a UIView, which is contained by a UIScrollView so that the user can scroll horizontally to look around the entire graph.

Now I want to zoom the graph when a user pinches in with two fingers, but instead of zooming in a view with the same rate for X and Y direction, I want to zoom only in the X direction by changing the X scale, without changing the Y scale.

I think I have to catch the pinch in/out gesture and redraw the graph, overriding the default zooming behavior.

But is there a way to do this?

I've been having a very difficult time to catch the pinch gesture on the UIScrollView, as it cancels the touches when it starts to scroll. I want the zooming to work even after the UIScrollView cancels the touches. :(

Thanks, Kura

回答1:

Although you cannot delete the existing pinch gesture recognizer, you can disable it and then add your own:

// Disable existing recognizer
for (UIGestureRecognizer* recognizer in [_scrollView gestureRecognizers]) {
    if ([recognizer isKindOfClass:[UIPinchGestureRecognizer class]]) {
        [recognizer setEnabled:NO];
    }
}

// Add our own
UIPinchGestureRecognizer* pinchRecognizer = 
  [[UIPinchGestureRecognizer alloc] initWithTarget:self 
                                            action:@selector(pinch:)];
[_scrollView addGestureRecognizer:pinchRecognizer];
[pinchRecognizer release];

Then in

- (void) pinch:(UIPinchGestureRecognizer*)recognizer { .. }

use

[recognizer locationOfTouch:0 inView:..]
[recognizer locationOfTouch:1 inView:..]

to figure out if the user is pinching horizontally or vertically.



回答2:

You should instead access the gestureRecognizers (defined in UIView), there are several of them being used by the scroll view,

figure out which one is the pinch recognizer and call removeGestureRecognizer: on the scroll view, then create your own and have it do the work, add it back with addGestureRecognizer:.

these are all public API, the recognizers and what order they are in are not (currently), so program defensively when accessing them

(this is a perfectly valid way to manipulate UIKit views, and Apple won't/shouldn't have issues with it - though they will not guarantee it works in any future release)



回答3:

You should be able to subclass UIScrollView and override the touchesBegan: method. Don't call [super touchesBegan:] but instead, adjust the zoom as you like:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    //Anything you want. Probably you would want to store all the touches
    //or their values, so that you can compare them to the touches
    //in the touchesEnded: method, 
    //thus letting you know what the pinch amount was
}

If you like, you can judge whether it's a pinch or not, and if it's not, call the super method, and only handle it yourself for custom pinches.



回答4:

Edsko & bshirley answers are good, but they don't tell where to place the code.

First, I placed it in viewDidLoad method, but no Pinch Gesture Recognizer was found in the scrollview (maybe because my scrollview is an IBOutlet).

Then I tried in viewWillAppear or viewDidAppear and the UIPinchGestureRecognizer was here.