UIPinchGestureRecognizer 中捏合缩放的最大/最小比例 - iPhone iOS

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5150642/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 19:03:57  来源:igfitidea点击:

Max/Min Scale of Pinch Zoom in UIPinchGestureRecognizer - iPhone iOS

iphoneipadioscgaffinetransform

提问by VinnyD

How would I be able to limit the scale of the UIPinchGestureRecognizer to a min and max level? The scale property below seems to be relative to the last known scale (the delta from last state) and I can't figure out how to set a limit to the size/heigh of the object being zoomed.

我将如何能够在UIPinchGestureRecognizer的规模限制在最小和最大水平?下面的 scale 属性似乎是相对于最后一个已知比例(从最后一个状态开始的增量),我无法弄清楚如何设置被缩放对象的大小/高度的限制。

-(void)scale:(id)sender {

[self.view bringSubviewToFront:[(UIPinchGestureRecognizer*)sender view]];

if([(UIPinchGestureRecognizer*)sender state] == UIGestureRecognizerStateEnded) {
    lastScale = 1.0;
    return;
}

CGFloat pinchscale = [(UIPinchGestureRecognizer*)sender scale];
CGFloat scale = 1.0 - (lastScale - pinchscale);
CGAffineTransform currentTransform = [(UIPinchGestureRecognizer*)sender view].transform;
CGAffineTransform holderTransform = holderView.transform;
CGAffineTransform newTransform = CGAffineTransformScale(currentTransform, scale, scale);
[[(UIPinchGestureRecognizer*)sender view] setTransform:newTransform];

lastScale = [(UIPinchGestureRecognizer*)sender scale];

}

}

采纳答案by Anomie

There isn't a way to limit the scale on a UIPinchGestureRecognizer. To limit the height in your code, you should be able to do something like this:

没有办法限制UIPinchGestureRecognizer. 要限制代码中的高度,您应该能够执行以下操作:

CGFloat scale = 1.0 - (lastScale - pinchscale);
CGRect bounds = [(UIPinchGestureRecognizer*)sender view].bounds;
scale = MIN(scale, maximumHeight / CGRectGetHeight(bounds));
scale = MAX(scale, minimumHeight / CGRectGetHeight(bounds));

To limit width, change 'Height' to 'Width' in the last two lines.

要限制宽度,请将最后两行中的“高度”更改为“宽度”。

回答by Paul Solt

Here is the solution that I figured out after using Anomie's answer as a starting point.

这是我在使用 Anomie 的答案作为起点后想出的解决方案。

- (void)handlePinchGesture:(UIPinchGestureRecognizer *)gestureRecognizer {

    if([gestureRecognizer state] == UIGestureRecognizerStateBegan) {
        // Reset the last scale, necessary if there are multiple objects with different scales
        lastScale = [gestureRecognizer scale];
    }

    if ([gestureRecognizer state] == UIGestureRecognizerStateBegan || 
        [gestureRecognizer state] == UIGestureRecognizerStateChanged) {

        CGFloat currentScale = [[[gestureRecognizer view].layer valueForKeyPath:@"transform.scale"] floatValue];

        // Constants to adjust the max/min values of zoom
        const CGFloat kMaxScale = 2.0;
        const CGFloat kMinScale = 1.0;

        CGFloat newScale = 1 -  (lastScale - [gestureRecognizer scale]); 
        newScale = MIN(newScale, kMaxScale / currentScale);   
        newScale = MAX(newScale, kMinScale / currentScale);
        CGAffineTransform transform = CGAffineTransformScale([[gestureRecognizer view] transform], newScale, newScale);
        [gestureRecognizer view].transform = transform;

        lastScale = [gestureRecognizer scale];  // Store the previous scale factor for the next pinch gesture call  
    }
}

回答by damian

The problem with most of the other answers is that they are trying to deal with scale as a linear value, when in fact it is non-linear due to the way UIPinchGestureRecognizercalculates its scale property based on the touch distance. When this isn't taken into account, the user must use more or less pinch distance to 'undo' the scaling applied by a previous pinch gesture.

大多数其他答案的问题在于他们试图将比例作为线性值处理,而实际上由于UIPinchGestureRecognizer基于触摸距离计算其比例属性的方式,它是非线性的。如果不考虑这一点,用户必须使用更多或更少的捏合距离来“撤消”先前捏合手势应用的缩放。

Consider: suppose transform.scale= 1.0and I place my fingers 6cm apart on the screen, then pinch inwards to 3cm apart - the resulting gestureRecognizer.scaleis 0.5, and 0.5-1.0is -0.5, so transform.scalewill become 1.0+(-0.5)= 0.5. Now, I lift my fingers, place them back down 3cm apart and pinch outwards to 6cm. The resulting gestureRecognizer.scalewill be 2.0, and 2.0-1.0is 1.0, so transform.scalewill become 0.5+1.0= 1.5. Not what I wanted to happen.

考虑:假设transform.scale=1.0并且我将我的手指分开 6 厘米放在屏幕上,然后向内捏合到分开 3 厘米 - 结果gestureRecognizer.scale0.50.5-1.0-0.5,所以transform.scale会变成1.0+(-0.5)= 0.5。现在,我抬起手指,将它们放回相距 3 厘米,然后向外捏合至 6 厘米。结果gestureRecognizer.scale将是2.02.0-1.01.0,所以transform.scale将成为0.5+1.0= 1.5。不是我想要发生的。

The fix is to calculate the delta pinch scale as a proportion of its previous value. I place my fingers down 6cm apart, and pinch inwards to 3cm, so gestureRecognizer.scaleis 0.5. 0.5/1.0is 0.5, so my new transform.scaleis 1.0*0.5= 0.5. Next, I place my fingers down 3cm apart, and pinch outwards to 6cm. gestureRecognizer.scaleis then 2.0, and 2.0/1.0is 2.0, so my new transform.scaleis 0.5*2.0= 1.0, which is exactly what I wanted to happen.

解决方法是将增量收缩比例计算为其先前值的比例。我将手指向下分开 6 厘米,然后向内捏 3 厘米,gestureRecognizer.scale也是0.50.5/1.0is 0.5,所以我的新transform.scale1.0*0.5= 0.5。接下来,我将手指向下分开 3 厘米,然后向外捏合至 6 厘米。gestureRecognizer.scaleis then2.02.0/1.0is 2.0,所以我的新transform.scale0.5*2.0= 1.0,这正是我想要发生的。

Here it is in code:

这是在代码中:

in -(void)viewDidLoad:

-(void)viewDidLoad

self.zoomGestureCurrentZoom = 1.0f;

in -(void)onZoomGesture:(UIPinchGestureRecognizer*)gestureRecognizer:

-(void)onZoomGesture:(UIPinchGestureRecognizer*)gestureRecognizer

if ( gestureRecognizer.state == UIGestureRecognizerStateBegan )
{
    self.zoomGestureLastScale = gestureRecognizer.scale;
}
else if ( gestureRecognizer.state == UIGestureRecognizerStateChanged )
{
    // we have to jump through some hoops to clamp the scale in a way that makes the UX intuitive
    float scaleDeltaFactor = gestureRecognizer.scale/self.zoomGestureLastScale;
    float currentZoom = self.zoomGestureCurrentZoom;
    float newZoom = currentZoom * scaleDeltaFactor;
    // clamp
    float kMaxZoom = 4.0f;
    float kMinZoom = 0.5f;
    newZoom = MAX(kMinZoom,MIN(newZoom,kMaxZoom));    
    self.view.transform = CGAffineTransformScale([[gestureRecognizer view] transform], newZoom, newZoom);

    // store for next time
    self.zoomGestureCurrentZoom = newZoom;
    self.zoomGestureLastScale = gestureRecognizer.scale;
}

回答by unsynchronized

I took some info gleaned from Paul Solt and Anoime's answers, and added that to an existing category I have made for UIViewController to allow making any UIView draggable, to now make it pinchable using gestures and transforms.

我从 Paul Solt 和 Anoime 的答案中收集了一些信息,并将其添加到我为 UIViewController 创建的现有类别中,以允许任何 UIView 可拖动,现在使用手势和变换使其可捏。

Note: this dirties the tag property of the view you are making draggable/pinchable. So if you needed the tag for something else, you can consider placing that value in the NSMutableDictionary being used by this technique. That's available as [self dictForView:theView]

注意:这会弄脏您正在制作的可拖动/可捏视图的标签属性。因此,如果您需要其他内容的标签,您可以考虑将该值放置在此技术使用的 NSMutableDictionary 中。这可作为[self dictForView:theView]

Implementing in your project:

在您的项目中实施:

You can make any subview within the view controllers "view" draggable or pinchable (or both) place a single line of code in your viewDidLoad (for example:)

您可以使视图控制器中的任何子视图“查看”可拖动或可捏(或两者)在您的 viewDidLoad 中放置一行代码(例如:)

[self makeView:mySubView draggable:YES pinchable:YES minPinchScale:0.75 maxPinchScale:1.0];

turn it off in viewDidUnload (releases guestures & dictionary):

在 viewDidUnload 中关闭它(发布guestures和字典):

[self makeView:mySubView draggable:NO pinchable:NO minPinchScale:1.0 maxPinchScale:1.0];

DragAndPinchScale.h file

DragAndPinchScale.h 文件

#import <UIKit/UIKit.h>

@interface UIViewController (DragAndPinchScale)

-(void) makeView:(UIView*)aView 
       draggable:(BOOL)draggable 
       pinchable:(BOOL)pinchable 
   minPinchScale:(CGFloat)minPinchScale
   maxPinchScale:(CGFloat)maxPinchScale;


-(NSMutableDictionary *) dictForView:(UIView *)theView;
-(NSMutableDictionary *) dictForViewGuestures:(UIGestureRecognizer *)guesture;

@end

DragAndPinchScale.m file

DragAndPinchScale.m 文件

#import "DragAndPinchScale.h"

@implementation UIViewController (DragAndPinchScale)


-(NSMutableDictionary *) dictForView:(UIView *)theView{
    NSMutableDictionary *dict = (NSMutableDictionary*) (void*) theView.tag;
    if (!dict) {
        dict = [[NSMutableDictionary dictionary ] retain];
        theView.tag = (NSInteger) (void *) dict;
    }

    return dict;

}


-(NSMutableDictionary *) dictForViewGuestures:(UIGestureRecognizer *)guesture {
    return [self dictForView:guesture.view];
}


- (IBAction)fingersDidPinchInPinchableView:(UIPinchGestureRecognizer *)fingers {
    NSMutableDictionary *dict = [self dictForViewGuestures:fingers];
    UIView *viewToZoom = fingers.view;
    CGFloat lastScale;
    if([fingers state] == UIGestureRecognizerStateBegan) {
        // Reset the last scale, necessary if there are multiple objects with different scales
        lastScale = [fingers scale];
    } else {
        lastScale = [[dict objectForKey:@"lastScale"] floatValue];
    }

    if ([fingers state] == UIGestureRecognizerStateBegan || 
        [fingers state] == UIGestureRecognizerStateChanged) {

        CGFloat currentScale = [[[fingers view].layer valueForKeyPath:@"transform.scale"] floatValue];

        // limits to adjust the max/min values of zoom
        CGFloat maxScale = [[dict objectForKey:@"maxScale"] floatValue];
        CGFloat minScale = [[dict objectForKey:@"minScale"] floatValue];

        CGFloat newScale = 1 -  (lastScale - [fingers scale]); 
        newScale = MIN(newScale, maxScale / currentScale);   
        newScale = MAX(newScale, minScale / currentScale);
        CGAffineTransform transform = CGAffineTransformScale([[fingers view] transform], newScale, newScale);
        viewToZoom.transform = transform;

        lastScale = [fingers scale];  // Store the previous scale factor for the next pinch gesture call  
    }

    [dict setObject:[NSNumber numberWithFloat:lastScale] 
             forKey:@"lastScale"];

}

- (void)fingerDidMoveInDraggableView:(UIPanGestureRecognizer *)finger {
    NSMutableDictionary *dict = [self dictForViewGuestures:finger];
    UIView *viewToDrag =  finger.view;
    if (finger.state == UIGestureRecognizerStateBegan) {

        [dict setObject:[NSValue valueWithCGPoint:viewToDrag.frame.origin] 
                 forKey:@"startDragOffset"];

        [dict setObject:[NSValue valueWithCGPoint:[finger locationInView:self.view]] 
                 forKey:@"startDragLocation"];


    }
    else if (finger.state == UIGestureRecognizerStateChanged) {

        NSMutableDictionary *dict = (NSMutableDictionary*) (void*) viewToDrag.tag;

        CGPoint stopLocation = [finger locationInView:self.view];
        CGPoint startDragLocation = [[dict valueForKey:@"startDragLocation"] CGPointValue];
        CGPoint startDragOffset = [[dict valueForKey:@"startDragOffset"] CGPointValue];
        CGFloat dx = stopLocation.x - startDragLocation.x;
        CGFloat dy = stopLocation.y - startDragLocation.y;
        //   CGFloat distance = sqrt(dx*dx + dy*dy );
        CGRect dragFrame = viewToDrag.frame;


        CGSize selfViewSize = self.view.frame.size;
        if (!UIDeviceOrientationIsPortrait(self.interfaceOrientation)) {
            selfViewSize = CGSizeMake(selfViewSize.height,selfViewSize.width);
        }

        selfViewSize.width  -= dragFrame.size.width;
        selfViewSize.height -= dragFrame.size.height;

        dragFrame.origin.x = MIN(selfViewSize.width, MAX(0,startDragOffset.x+dx));
        dragFrame.origin.y = MIN(selfViewSize.height,MAX(0,startDragOffset.y+dy));

        viewToDrag.frame = dragFrame;
    }
    else if (finger.state == UIGestureRecognizerStateEnded) {

        [dict removeObjectForKey:@"startDragLocation"];
        [dict removeObjectForKey:@"startDragOffset"];
    }
}

-(void) makeView:(UIView*)aView 
       draggable:(BOOL)draggable 
       pinchable:(BOOL)pinchable 
   minPinchScale:(CGFloat)minPinchScale
   maxPinchScale:(CGFloat)maxPinchScale{
    NSMutableDictionary *dict = (NSMutableDictionary*) (void*) aView.tag;

    if (!(pinchable || draggable)) {

        if (dict){ 
            [dict release];
            aView.tag = 0;
        }
        return;
    }

    if (dict) {

        UIPanGestureRecognizer *pan =[dict objectForKey:@"UIPanGestureRecognizer"];
        if(pan){
            if ([aView.gestureRecognizers indexOfObject:pan]!=NSNotFound) {
                [aView removeGestureRecognizer:pan];
            }
            [dict removeObjectForKey:@"UIPanGestureRecognizer"];
        }

        UIPinchGestureRecognizer *pinch =[dict objectForKey:@"UIPinchGestureRecognizer"];
        if(pinch){
            if ([aView.gestureRecognizers indexOfObject:pinch]!=NSNotFound) {
                [aView removeGestureRecognizer:pinch];
            }
            [dict removeObjectForKey:@"UIPinchGestureRecognizer"];
        }

        [dict removeObjectForKey:@"startDragLocation"];
        [dict removeObjectForKey:@"startDragOffset"];
        [dict removeObjectForKey:@"lastScale"];
        [dict removeObjectForKey:@"minScale"];
        [dict removeObjectForKey:@"maxScale"];
    }


    if (draggable) {

        UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(fingerDidMoveInDraggableView:)];
        pan.minimumNumberOfTouches = 1;  
        pan.maximumNumberOfTouches = 1;  
        [aView addGestureRecognizer:pan];
        [pan release];

        dict = [self dictForViewGuestures:pan];
        [dict setObject:pan forKey:@"UIPanGestureRecognizer"];

    }

    if (pinchable) {


        CGAffineTransform initialTramsform = CGAffineTransformMakeScale(1.0, 1.0);
        aView.transform = initialTramsform;


        UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(fingersDidPinchInPinchableView:)];
        [aView addGestureRecognizer:pinch];
        [pinch release];
        dict = [self dictForViewGuestures:pinch];
        [dict setObject:pinch forKey:@"UIPinchGestureRecognizer"];
        [dict setObject:[NSNumber numberWithFloat:minPinchScale] forKey:@"minScale"];
        [dict setObject:[NSNumber numberWithFloat:maxPinchScale] forKey:@"maxScale"];


    }

}

@end

回答by Shagun

Thanks, really useful code snippet above clamping to a minimum and maximum scale.

谢谢,上面的代码片段非常有用,可以限制到最小和最大比例。

I found that when I flipped the view first using:

我发现当我首先使用以下方法翻转视图时:

CGAffineTransformScale(gestureRecognizer.view.transform, -1.0, 1.0); 

it would cause a flicker when scaling the view.

缩放视图时会导致闪烁。

Let me know what you think but the solution for me was to update the code sample above, and if the view has been flipped (flag set via property) then invert the scale value:

让我知道您的想法,但我的解决方案是更新上面的代码示例,如果视图已翻转(标志通过属性设置),则反转比例值:

if ([gestureRecognizer state] == UIGestureRecognizerStateBegan || [gestureRecognizer     state] == UIGestureRecognizerStateChanged)
{
    CGFloat currentScale = [[[gestureRecognizer view].layer valueForKeyPath:@"transform.scale"] floatValue];

    if(self.isFlipped) // (inverting)
    {
        currentScale *= -1;
    }

    CGFloat newScale = 1 -  (self.lastScale - [gestureRecognizer scale]);

    newScale = MIN(newScale, self.maximumScaleFactor / currentScale);
    newScale = MAX(newScale, self.minimumScaleFactor / currentScale);

    CGAffineTransform transform = CGAffineTransformScale([[gestureRecognizer view] transform], newScale, newScale);
    gestureRecognizer.view.transform = transform;

    self.lastScale = [gestureRecognizer scale];  // Store the previous scale factor for the next pinch gesture call

回答by Fu Jiantao

Method 1

方法一

gestureRecognizer.scalestart with 1.0 at the beginning of pinch (gestureRecognizer.state == .began), and gestureRecognizer.scalein later state (.changed or .end) is always based on that, for example, if the view size is view_sizeat the beginning of pinch (might not be the same with the original size orig_view_size), gestureRecognizer.scalealways starts with 1.0, and if it becomes 2.0 later, it's size will be 2 * view_size, so the scale always based on that when the pinch starts.

gestureRecognizer.scale从 1.0 开始捏 (gestureRecognizer.state == .began) 开始,并且gestureRecognizer.scale在以后的状态 (.changed 或 .end) 始终基于此,例如,如果视图大小view_size在捏的开头(可能与原来的大小不一样orig_view_size),gestureRecognizer.scale总是从1.0开始,如果以后变成2.0,它的大小就会是2 * view_size,所以比例总是以捏开始时的大小为准。

And we can get the scale at the beginning of pinch (gestureRecognizer.state == .began)lastScale = self.imageView.frame.width/self.imageView.bounds.size.width, so the scale of the original image now should be lastScale * gestureRecognizer.scale

并且我们可以得到pinch开始时的比例(gestureRecognizer.state == .began)lastScale = self.imageView.frame.width/self.imageView.bounds.size.width,所以现在原图的比例应该是lastScale * gestureRecognizer.scale

  • lastScale: The scale of last round of Pinch, a round of Pinch is from state.start to state.end, and the scale is based on the original view size.

  • gestureRecognizer.scale: current scale, based on the view size after last round of Pinch.

  • currentScale: current scale, based on the orignial view size.

  • newScale: new scale, based on the orignial view size. newScale = lastScale * gestureRecognizer.scale, and you can limit the scale of the view by comparing the limitation with newScale.

  • lastScale:上一轮Pinch的比例,一轮Pinch是从state.start到state.end,比例以原视图大小为准。

  • gestureRecognizer.scale:当前比例,基于上一轮捏合后的视图大小。

  • currentScale:当前比例,基于原始视图大小。

  • newScale:基于原始视图大小的新比例。newScale = lastScale * gestureRecognizer.scale,您可以通过将限制与 进行比较来限制视图的比例newScale

```

``

var lastScale:CGFloat = 1.0

@objc func handlePinch(_ gestureRecognizer: UIPinchGestureRecognizer) {
        var newScale = gestureRecognizer.scale
        if gestureRecognizer.state == .began {
            lastScale = self.imageView.frame.width/self.imageView.bounds.size.width
        }
        newScale = newScale * lastScale

        if newScale < minScale {
            newScale = minScale
        } else if newScale > maxScale {
            newScale = maxScale
        }

        let currentScale = self.imageView.frame.width/self.imageView.bounds.size.width
        self.imageView.transform = CGAffineTransform(scaleX: newScale, y: newScale)
        print("last Scale: \(lastScale), current scale: \(currentScale), new scale: \(newScale), gestureRecognizer.scale: \(gestureRecognizer.scale)")
}

```

``

Method 2

方法二

gestureRecognizer.scalestart with 1.0 on each Pinch notification, this require you reset gestureRecognizer.scale = 1in the code in the end of each notification handler, so now gestureRecognizer.scaleis based on the view size of last Pinch notification, NOT based on the view size at the beginning of pinch. This is the most important difference with method 1. And since we don't rely on the scale of last round, we don't need lastScaleanymore.

gestureRecognizer.scale每个 Pinch 通知从 1.0 开始,这需要您gestureRecognizer.scale = 1在每个通知处理程序末尾的代码中重置,所以现在gestureRecognizer.scale是基于最后一个 Pinch 通知的视图大小,而不是基于 pinch 开头的视图大小。这是与方法1最重要的区别。而且由于我们不依赖上一轮的规模,所以我们不再需要lastScale了。

  • currentScale: current scale, based on the orignial view size.

  • gestureRecognizer.scale: new scale, based on the view size of last Pinch (not the last round), the scale value based on the orignial view size will be currentScale * gestureRecognizer.scale

  • currentScale:当前比例,基于原始视图大小。

  • gestureRecognizer.scale: 新比例,基于上次捏合(不是最后一轮)视图大小,基于原始视图大小的比例值将是currentScale * gestureRecognizer.scale

And we use transform.scaledBynow, which use the scale based on view size of last Pinch (not the last round).

我们transform.scaledBy现在使用,它使用基于最后一个捏(不是最后一轮)的视图大小的比例。

```

``

@objc func handlePinch(_ gestureRecognizer: UIPinchGestureRecognizer) {
        let currentScale = self.imageView.frame.width/self.imageView.bounds.size.width
        var newScale = gestureRecognizer.scale
        if currentScale * gestureRecognizer.scale < minScale {
            newScale = minScale / currentScale
        } else if currentScale * gestureRecognizer.scale > maxScale {
            newScale = maxScale / currentScale
        }
        self.imageView.transform = self.imageView.transform.scaledBy(x: newScale, y: newScale)

        print("current scale: \(currentScale), new scale: \(newScale)")

        gestureRecognizer.scale = 1
}

```

``

回答by Kevin_TA

Other approaches mentioned here did not work for me, but taking a couple things from previous answers and (in my opinion) simplifying things, I've got this to work for me. effectiveScaleis an ivar set to 1.0 in viewDidLoad.

这里提到的其他方法对我不起作用,但是从以前的答案中提取一些东西并且(在我看来)简化了事情,我已经得到了这个对我有用。effectiveScale是一个实例变量设置为在1.0 viewDidLoad

-(void)zoomScale:(UIPinchGestureRecognizer *)recognizer
{
    if([recognizer state] == UIGestureRecognizerStateEnded) {
        // Reset last scale
        lastScale = 1.0;
        return;
    }

    if ([recognizer state] == UIGestureRecognizerStateBegan ||
    [recognizer state] == UIGestureRecognizerStateChanged) {

        CGFloat pinchscale = [recognizer scale];
        CGFloat scaleDiff = pinchscale - lastScale;

        if (scaleDiff < 0)
            scaleDiff *= 2; // speed up zoom-out
        else
            scaleDiff *= 0.7; // slow down zoom-in

        effectiveScale += scaleDiff;
        // Limit scale between 1 and 2
        effectiveScale = effectiveScale < 1 ? 1 : effectiveScale;
        effectiveScale = effectiveScale > 2 ? 2 : effectiveScale;

        // Handle transform in separate method using new effectiveScale    
        [self makeAndApplyAffineTransform];
        lastScale = pinchscale;
    }
}

回答by Arvind Kumar

- (void)handlePinch:(UIPinchGestureRecognizer *)recognizer{

    //recognizer.scale=1;

    CGFloat pinchScale = recognizer.scale;
    pinchScale = round(pinchScale * 1000) / 1000.0;
    NSLog(@"%lf",pinchScale);

if (pinchScale < 1)

 {

 currentLabel.font = [UIFont fontWithName:currentLabel.font.fontName size:

(currentLabel.font.pointSize - pinchScale)];

   recognizer.view.transform = CGAffineTransformScale(recognizer.view.transform, recognizer.scale, recognizer.scale);

 [currentLabel sizeToFit];

  recognizer.scale=1;
    }
  else
    {
        currentLabel.font = [UIFont fontWithName:currentLabel.font.fontName size:(currentLabel.font.pointSize + pinchScale)];

         recognizer.view.transform = CGAffineTransformScale(recognizer.view.transform, recognizer.scale, recognizer.scale);

         [currentLabel sizeToFit];

        recognizer.scale=1;
    }
    //currentLabel.adjustsFontSizeToFitWidth = YES;

   // [currentLabel sizeToFit];
    NSLog(@"Font :%@",label.font);
}

回答by Roman Solodyashkin

- (void)pinchToZoom:(UIPinchGestureRecognizer*)gesture
{
    switch (gesture.state)
    {
        case UIGestureRecognizerStateBegan:
        {
            lastScale = gesture.scale;
        }break;
        case UIGestureRecognizerStateChanged:
        {   
            const CGFloat zoomSensitivity = 5;
            const CGFloat zoomMin = 1;
            const CGFloat zoomMax = 16;

            CGFloat objectScale = gesture.view.contentScaleFactor;
            CGFloat zoomDiff = lastScale - gesture.scale;
            CGFloat zoomDirty = objectScale - zoomDiff * zoomSensivity;
            CGFloat zoomTo = fmaxf(zoomMin, fminf(zoomDirty, zoomMax));

            // step round if needed (neutralize elusive changes)
            zoomTo = (NSInteger)(zoomTo * 10) * 0.1;

            if ( objectScale != zoomTo )
                gesture.view.contentScaleFactor = zoomTo;

            lastScale = gesture.scale;
        }break;
        default:
            break;
    }
}

回答by micmcg

Can you use a scroll view instead? Then you could use scrollView.minimumZoomScale and scrollView.maximumZoomScale

你可以使用滚动视图吗?然后你可以使用 scrollView.minimumZoomScale 和 scrollView.maximumZoomScale